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

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


person Nero    schedule 14.11.2010    source источник
comment
Шаблон стратегии может использовать внедрение зависимостей   -  person TechWisdom    schedule 22.06.2015


Ответы (9)


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

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

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

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

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

person eljenso    schedule 14.11.2010
comment
Интерфейс, используемый в DI только с одной реализацией, очень распространен - ​​тогда что же такое DI в данном конкретном случае? - person Kalpesh Soni; 26.09.2013
comment
Эта цитата в основном все объясняет: in a DI scenario it is more unusual that the dependencies of objects change during their lifetimes, while this is not uncommon with Strategy - person Sergey Telshevsky; 22.05.2014
comment
Стратегия: классы разработаны таким образом, чтобы их можно было настроить с помощью алгоритма во время выполнения. DI: Такие классы получают алгоритм (объект стратегии), внедряемый во время выполнения. Из памяти шаблонов дизайна GoF по адресу w3sdesign.com. - person GFranke; 06.02.2017

Разница в том, чего они пытаются достичь. Шаблон стратегии используется в ситуациях, когда вы знаете, что хотите поменять реализации. Например, вы можете захотеть отформатировать данные по-разному - вы можете использовать шаблон стратегии для замены модуля форматирования 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());

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

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

person tsimon    schedule 14.11.2010

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

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

person James Black    schedule 05.05.2009
comment
Я думаю, что понимаю вашу суть, но я не могу правильно выразить это словами ... Итак, вы говорите, что DI - это скорее шаблон реализации, в то время как стратегия - это больше шаблон дизайна, и один из способов реализации стратегии - через DI? - person Robert Gould; 05.05.2009
comment
Звучит неплохо. DI - это больше, чем просто шаблон стратегии. Я обнаружил ту же путаницу с АОП, когда люди думают, что это заводской шаблон. Я думаю, что DI может реализовать шаблон стратегии, так что ваша переформулировка будет фантастической. :) - person James Black; 05.05.2009

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

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

DI:

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

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

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

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

person Jahan    schedule 14.11.2010
comment
Мне особенно нравится роль чувака в твоем объяснении. :-) - person johey; 17.07.2019

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

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


Пример стратегии:

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 проверки. Они использовали общедоступные данные в тестовом двойнике, который был введен в тестируемый класс. Я не мог этого сделать с производственным кодом из-за принципа сокрытия данных. Я не хотел, чтобы код специального назначения был вставлен в производственный код. Публичные данные должны принадлежать к другому классу.

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

person Edward Ames    schedule 10.05.2009

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

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

person Andrew W. Phillips    schedule 01.08.2011

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

person Calvin    schedule 13.09.2011

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

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

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

На самом деле стратегия не говорит о внедрении зависимостей. При необходимости это можно сделать с помощью абстрактной фабрики внутри шаблона стратегии. Стратегия говорит только о создании семейства классов с интерфейсом и «игре» с ним. Если во время игры мы обнаружим, что классы находятся на другом уровне, мы должны внедрить его сами, но это не задача Стратегии.

person Blue Clouds    schedule 23.10.2012

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

person Sumeet Patil    schedule 17.05.2018
comment
Я не уверен, что понимаю, не могли бы вы подробнее рассказать о том, как стратегия соотносится с принципом открытия / закрытия и как DI соотносится с DIP? - person Adam Parkin; 18.09.2018