В чем разница между стратегическим шаблоном и инъекцией зависимостей?


шаблон стратегии и инъекция зависимостей позволяют нам устанавливать / вводить объекты во время выполнения. В чем разница между стратегическим шаблоном и инъекцией зависимостей?

9 84

9 ответов:

DI и стратегия работают одинаково, но стратегия используется для более мелкозернистых и недолговечных зависимостей.

когда объект настроен с "фиксированной" стратегией, например, когда объект построен, различие между стратегией и DI размывается. Но в сценарии DI более необычно, что зависимости объектов меняются в течение их жизни, в то время как это не редкость для стратегии.

кроме того, вы можете передавать стратегии в качестве аргументов методы, в то время как связанная с ними концепция введения аргумента метода не является широко распространенной и в основном используется только в контексте автоматизированного тестирования.

стратегия фокусируется на намерениях и поощряет вас создавать интерфейс с различными реализациями, которые подчиняются одному и тому же поведенческому контракту. DI-это скорее просто реализация некоторого поведения и его предоставление.

с DI вы можете разложить свою программу по другим причинам, чем просто иметь возможность менять части реализация. Интерфейс, используемый в DI только с одной реализацией, очень распространен. "Стратегия" с одной конкретной реализацией (когда-либо) не является реальной проблемой, но, вероятно, ближе к DI.

разница в том, что они пытаются достичь. Шаблон стратегии используется в ситуациях, когда вы знаете, что хотите поменять реализации. Например, вы можете форматировать данные по - разному-вы можете использовать шаблон стратегии для замены XML-форматера или CSV-форматера и т. д.

инъекция зависимостей отличается тем, что пользователь не пытается изменить поведение среды выполнения. Следуя приведенному выше примеру, мы можем создавать экспорт XML программа, которая использует XML-форматирования. Вместо того, чтобы структурировать код следующим образом:

public class DataExporter() {
  XMLFormatter formatter = new XMLFormatter();
}

вы бы "впрыснули" форматер в конструктор:

public class DataExporter {
  IFormatter formatter = null;

  public DataExporter(IDataFormatter dataFormatter) {
    this.formatter = dataFormatter;
  }
}

DataExporter exporter = new DataExporter(new XMLFormatter());

есть несколько оправданий для инъекции зависимостей, но основной-для тестирования. У вас может быть случай, когда у вас есть какой-то механизм сохранения (например, база данных). Тем не менее, это может быть боль, чтобы использовать реальную базу данных, когда вы запускаете тесты повторно. Итак, для ваших тестовых случаев вы бы внедрите фиктивную базу данных, чтобы вы не несли этих накладных расходов.

используя этот пример, вы можете увидеть разницу: мы всегда планируем использовать стратегию хранения данных, и это тот, который мы передаем (реальный экземпляр БД). Однако при разработке и тестировании мы хотим использовать разные зависимости, поэтому мы вводим разные конкреции.

вы можете использовать DI в качестве шаблона стратегии, поэтому вы можете поменять алгоритм, необходимый для каждого клиента, но DI может выйти за рамки этого, поскольку это способ просто отделить части приложения, которые не будут частью шаблона стратегии.

было бы рискованно сказать, что DI-это просто переименованный шаблон стратегии, поскольку это начинает разбавлять то, для чего на самом деле существует шаблон стратегии, IMO.

чувак, инъекция зависимости-это более общий шаблон, и речь идет о зависимости от абстракций, а не конкреций, и это часть каждого шаблона, но шаблон стратегии-это решение более конкретной проблемы

это определение из Википедии:

DI:

инъекция зависимостей (DI) in объектно-ориентированное программирование шаблон дизайна с ядром принцип отделения поведения от разрешение зависимостей. В других слова: метод для развязки высоко зависимые программные компоненты.

Стратегия Шаблон:

в компьютерном программировании, стратегии шаблон (также известный как политика pattern) - это конкретное программное обеспечение шаблон проектирования, с помощью которого алгоритмы могут выбирается во время выполнения.

шаблон стратегии предназначен для предоставить средства для определения семейства алгоритмов, инкапсуляции каждого из них объект, и сделать их сменный. Шаблон стратегии позволяет алгоритмы различаются независимо от клиенты, которые их используют.

стратегии-это вещи более высокого уровня, которые используются для изменения способа вычисления. С помощью инъекции зависимостей вы можете изменить не только то, как все вычисляется, но и изменить то, что есть.

для меня это становится понятно при использовании модульных тестов. Для выполнения производственного кода у вас есть все скрытые данные (т. е. частные или защищенные); в то время как при модульных тестах большая часть данных является общедоступной, поэтому я могу посмотреть на нее с утверждениями.


пример стратегия:

public class Cosine {
  private CalcStrategy strat;

  // Constructor - strategy passed in as a type of DI
  public Cosine(CalcStrategy s) {
    strat = s;
  }
}

public abstract class CalcStrategy {
  public double goFigure(double angle);
}

public class RadianStrategy extends CalcStrategy {
  public double goFigure(double angle) {
    return (...);
  }
}
public class DegreeStrategy extends CalcStrategy {
  public double goFigure(double angle) {
    return (...);
  }
}

обратите внимание, что нет никаких публичных данных, которые отличаются между стратегиями. И нет никаких других методов. Обе стратегии имеют одинаковые функции и сигнатуры.


Теперь для инъекции зависимостей:

public class Cosine {
  private Calc strat;

  // Constructor - Dependency Injection.
  public Cosine(Calc s) {
    strat = s;
  }
}

public class Calc {
  private int numPasses = 0;
  private double total = 0;
  private double intermediate = 0;

  public double goFigure(double angle) {
    return(...);
}

public class CalcTestDouble extends Calc {
  // NOTICE THE PUBLIC DATA.
  public int numPasses = 0;
  public double total = 0;
  public double intermediate = 0;
  public double goFigure(double angle) {
    return (...);
  }
}

использование:

public CosineTest {

  @Test
  public void testGoFigure() {
    // Setup
    CalcTestDouble calc = new CalcTestDouble();
    Cosine instance = new Cosine(calc);

    // Exercise
    double actualAnswer = instance.goFigure(0.0);

    // Verify
    double tolerance = ...;
    double expectedAnswer = ...;
    assertEquals("GoFigure didn't work!", expectedAnswer,
         actualAnswer, tolerance);

    int expectedNumPasses = ...;
    assertEquals("GoFigure had wrong number passes!",
        expectedNumPasses, calc.numPasses);

    double expectedIntermediate = ...;
    assertEquals("GoFigure had wrong intermediate values!",
        expectedIntermediate, calc.intermediate, tolerance);
  }
}

обратите внимание на последние 2 проверки. Они использовали открытые данные в тестовом двойнике, который был введен в тестируемый класс. Я не мог сделать это с производственным кодом, потому что данных принцип сокрытия. Я не хотел, чтобы специальный тестовый код был вставлен в производственный код. Публичные данные должны были быть в другом классе.

был впрыснут двойник теста. Это отличается от просто стратегии, так как это повлияло данные и не только функции.

инъекция зависимостей-это уточнение шаблона стратегии, которое я кратко объясню. Часто необходимо выбирать между несколькими альтернативными модулями во время выполнения. Все эти модули реализуют общий интерфейс, так что их можно использовать взаимозаменяемо. Цель шаблона стратегии состоит в том, чтобы снять бремя принятия решения о том, какой из модулей использовать (т. е. какая "конкретная стратегия" или зависимость), инкапсулируя процесс принятия решений в отдельный объект, который я вызовет объект стратегии.

инъекция зависимостей уточняет шаблон стратегии, не только решая, какую конкретную стратегию использовать, но и создавая экземпляр конкретной стратегии и "впрыскивая" его обратно в вызывающий модуль. Это полезно, даже если существует только одна зависимость, поскольку знание того, как управлять (инициализировать и т. д.) конкретным экземпляром стратегии, также может быть скрыто в объекте стратегии.

на самом деле, инъекция зависимостей также очень похожа на шаблон моста. Для меня (и в соответствии с определением), шаблон моста для размещения различных версии реализации, в то время как шаблон стратегии для совершенно другой логики. Но пример кода выглядит так, как будто он использует DI. Так что, может быть, DI-это просто техника или реализация?

стратегия-это арена для использования ваших навыков инъекции зависимостей. Реальные способы реализации инъекции зависимостей заключаются в следующем: -

  1. событий
  2. конфигурационные файлы карты unity / structure (или программно) и т. д.
  3. Методы Расширения
  4. абстрактный узор завод
  5. инверсия шаблона управления (используется как стратегией, так и абстрактной фабрикой)

есть одна вещь, хотя это делает стратегию стоит отдельно. Как вы знаете, в Unity при запуске приложения все зависимости установлены, и мы не можем изменить его дальше. Но стратегия поддерживает изменение зависимостей во время выполнения. Но мы должны управлять / вводить зависимость, а не ответственность стратегии!

на самом деле стратегия не говорит о инъекции зависимости. При необходимости это можно сделать через абстрактную фабрику внутри шаблона стратегии. Стратегия говорит только о создании семейства классов с интерфейсом и "игре" с ним. В то время как играя, если мы обнаружим, что классы находятся на другом уровне, то мы должны ввести его сами, но не работу стратегии.

Если мы рассмотрим твердые принципы - Мы используем шаблон стратегии для открытого закрытого принципа и инъекции зависимостей для принципа инверсии зависимостей