В чем разница между шаблоном стратегии и внедрением зависимости? - PullRequest
88 голосов
/ 14 ноября 2010

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

Ответы [ 9 ]

95 голосов
/ 14 ноября 2010

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

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

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

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

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

36 голосов
/ 14 ноября 2010

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

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

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

27 голосов
/ 05 мая 2009

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

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

12 голосов
/ 14 ноября 2010

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

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

DI:

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

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

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

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

6 голосов
/ 10 мая 2009

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

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

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

3 голосов
/ 01 августа 2011

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

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

1 голос
/ 14 сентября 2011

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

0 голосов
/ 17 мая 2018

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

0 голосов
/ 23 октября 2012

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

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

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

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

...