Как работает шаблон стратегии?

Как это работает, для чего оно используется и когда нужно его использовать?

Ответ 1

Давайте объясним шаблон стратегии простым способом:

У вас есть класс Car() с методом run(), поэтому вы используете его таким образом на псевдоязыке:

mycar = new Car()
mycar.run()

Теперь вы можете изменить поведение run() на лету во время выполнения программы. Например, вы можете имитировать отказ двигателя или использовать кнопку "повышения" в видеоигре.

Есть несколько способов сделать это моделирование: использование условных операторов и переменной флага - один из способов. Другой шаблон стратегии: он делегирует поведение метода run() другому классу:

Class Car()
{
    this.motor = new Motor(this) 

    // passing "this" is important for the motor so it knows what it is running

    method run()
    {
        this.motor.run()
    }

    method changeMotor(motor)
    {
        this.motor = motor 
    }

}

Если вы хотите изменить поведение автомобиля, вы можете просто изменить мотор. (Легче в программе, чем в реальной жизни, верно? ;-))

Это очень полезно, если у вас много сложных состояний: вы можете изменять и поддерживать их гораздо проще.

Ответ 2

Проблема

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

Пример кода

namespace StrategyPatterns
{
  // Interface definition for a Sort algorithm
  public interface ISort
  {
    void Sort(List<string> list)
  }

  // QuickSort implementation
  public class CQuickSorter : ISort
  {
    void Sort(List<string> list)
    {
      // Here will be the actual implementation
    }
  }

  // BubbleSort implementation
  public class CBubbleSort : ISort
  {
    void Sort(List<string> list)
    {
      // The actual implementation of the sort
    }
  }

  // MergeSort implementation
  public class CMergeSort : ISort
  {
    void Sort(List<string> list)
    {
      // Again the real implementation comes here
    }
  }

  public class Context
  {
    private ISort sorter;

    public Context(ISort sorter)
    {
      // We pass to the context the strategy to use
      this.sorter = sorter;
    }

    public ISort Sorter
    {
      get{return sorter;)
    }
  }

  public class MainClass
  {
    static void Main()
    {
       List<string> myList = new List<string>();

       myList.Add("Hello world");
       myList.Add("Another item");
       myList.Add("Item item");

       Context cn = new Context(new CQuickSorter());
       // Sort using the QuickSort strategy
       cn.Sorter.Sort(myList);
       myList.Add("This one goes for the mergesort");
       cn = new Context(new CMergeSort());
       // Sort using the merge sort strategy
       cn.Sorter.Sort(myList);
    }
  }
}

Ответ 3

  • Что такое стратегия? Стратегия - это план действий, предназначенный для достижения конкретной цели;
  • "Определите семейство алгоритмов, инкапсулируйте каждый из них и сделайте их взаимозаменяемыми. Стратегия позволяет алгоритму независимо от клиентов, которые его используют". (Банда четырех);
  • Определяет набор классов, каждый из которых представляет потенциальное поведение. Переключение между этими классами изменяет поведение приложения. (Стратегия);
  • Это поведение можно выбрать во время выполнения (с использованием полиморфизма) или времени разработки;
  • Захватить абстракцию в интерфейсе, похоронить детали реализации в производных классах;

enter image description here

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

  • Хорошее использование:

    • Когда у нас есть набор подобных алгоритмов и его необходимость переключаться между ними в разных частях приложения. С шаблоном стратегии можно избежать ifs и облегчить обслуживание;
    • Когда мы хотим добавить новые методы в суперкласс, который не обязательно имеет смысл для каждого подкласса. Вместо традиционного использования интерфейса, добавляя новый метод, мы используем переменную экземпляра, которая является подклассом нового интерфейса Functionality. Это называется композицией: вместо наследования способности через наследование класс состоит из объектов с правильной способностью;

Ответ 4

Непосредственно из Шаблон стратегии Wikipedia article:

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

Ответ 5

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

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

  • В шаблоне Стратегия компонент, выполняющий стратегию, является зависимостью, предоставляемой входящему (использующему) компоненту через его конструктор или сеттер (согласно вашей религии). Используемый компонент полностью не знает, какая стратегия используется; стратегия всегда вызывается через интерфейс.

Кто-нибудь знает какие-либо другие отличия?

Ответ 6

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

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