Использование шаблона стратегии и шаблона команды - PullRequest
118 голосов
/ 07 октября 2010

Оба шаблона разработки инкапсулируют алгоритм и отделяют детали реализации от их вызывающих классов.Единственное отличие, которое я могу заметить, состоит в том, что шаблон Стратегии принимает параметры для выполнения, а шаблон Command - нет.

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

Какие определения определяют, использовать ли один шаблон или другой?

Ответы [ 7 ]

91 голосов
/ 09 октября 2010

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

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

design pattern encapsulation hierarchy table

Как видно из таблицы, объект Pattern Strategy скрывает детали реализации алгоритма, поэтому использование другогоОбъект стратегии будет выполнять ту же функциональность, но другим способом.Каждый объект стратегии может быть оптимизирован для определенного фактора или работать по какому-либо другому параметру;и благодаря использованию общего интерфейса контекст может безопасно работать с любым из них.

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

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

48 голосов
/ 07 октября 2010

Стратегии инкапсулируют алгоритмы. Команды отделяют отправителя от получателя запроса, они превращают запрос в объект.

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

24 голосов
/ 13 августа 2014

Отвечая на очень старый вопрос.(кто-нибудь видит последние ответы вместо самых проголосовавших?)

Это действительно путаница из-за сходства.Шаблоны стратегии и команды используют инкапсуляцию .Но это не делает их одинаковыми.

Ключевым отличием является понимание того, что заключено в капсулу.Принцип ОО, от которого зависят обе модели: Инкапсулирует то, что меняется .

В случае стратегии, что меняется, это алгоритм .Например, один объект стратегии знает, как выводить в файл XML, а другой выводит, скажем, в JSON.Различные алгоритмы хранятся ( инкапсулированы ) в разных классах.Это так просто.

В случае команды меняется только запрос .Запрос может поступить от File Menu > Delete или Right Click > Context Menu > Delete или Just Delete Button pressed.Все три случая могут генерировать 3 командных объекта одного типа.Эти объекты команд представляют только 3 запроса на удаление;не алгоритм удаления.Поскольку запросы теперь представляют собой кучу объектов, мы могли бы легко ими управлять.Внезапно становится тривиально предоставлять такие функции, как отмена или повтор.

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

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

Я думаю, что Command помогает нам расширить наше понимание инкапсуляции, в то время как Стратегия обеспечивает естественное использование инкапсуляции иполиморфизм.

15 голосов
/ 07 октября 2010

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

Возможно, сначала попробуйте StrategyOne,если результаты не достаточно хороши, попробуйте StrategyTwo ...

Команды связаны с различными вещами, которые должны произойти, например TryToWalkAcrossTheRoomCommand.Эта команда будет запускаться всякий раз, когда какой-либо объект должен попытаться пройти через комнату, но внутри него он может попробовать StrategyOne и StrategyTwo для попытки пройти через комнату.

Mark

7 голосов
/ 07 октября 2010

Я могу ошибаться, но я воспринимаю команду как функцию для выполнения или реакцию.Должно быть как минимум два игрока: тот, кто запрашивает действие, и тот, кто выполняет действие.Графический интерфейс пользователя является типичным примером для шаблона команды:

  • Все кнопки на панели инструментов приложения связаны с каким-либо действием.
  • В этом случае кнопка является исполнителем.
  • Действие являетсякоманда в этом случае.

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

Стратегия немного отличается: она больше привязана к некоторой области.Стратегия может определять правило для форматирования даты (в формате UTC «специфично для локали») (стратегия «средство форматирования даты») или для вычисления квадрата для геометрической фигуры (стратегия «квадратный калькулятор»).В этом смысле стратегии - это легковесные объекты, которые принимают что-то в качестве входных данных («дата», «цифра», ...) и принимают решение на его основе.Возможно, не самый лучший, но хороший пример стратегии связан с интерфейсом javax.xml.transform.Source: в зависимости от того, является ли переданный объект DOMSource или SAXSource или StreamSource, стратегия (= преобразователь XSLT в данном случае) будет применяться по-разному.правила для обработки.Реализация может быть простой switch или включать шаблон цепочки ответственности .

Но на самом деле между этими двумя шаблонами есть нечто общее: команды и стратегии инкапсулируют алгоритмы в одной семантической области.

4 голосов
/ 26 января 2016

Команда:

Основные компоненты:

  1. Команда объявляет интерфейс для абстрактных команд, таких как execute()
  2. Получатель знает, как выполнить конкретную команду
  3. Invoker содержит ConcreteCommand , который должен быть выполнен
  4. Клиент создает ConcreteCommand и назначает Получатель
  5. ConcreteCommand определяет привязку между Команда и Приемник

Workflow:

Клиент звонки Invoker => Invoker звонки ConcreteCommand => ConcreteCommand звонки Получатель метод, который реализует абстрактный Команда метод.

Преимущество : На клиента не влияют изменения в Команде и Получателе. Invoker обеспечивает слабую связь между Клиентом и Получателем. Вы можете запустить несколько команд с одним и тем же Invoker.

Шаблон Command позволяет вам выполнить команду на разных Приемниках , используя тот же Invoker . Invoker не знает тип Receiver

Для лучшего понимания концепций, взгляните на эту статью JournalDev от Pankaj Kumar и dzone article от James Sugrue in дополнение к ссылке в Википедии.

Вы можете использовать Command pattern для

  1. Разъединить призывателя и получателя команды

  2. Реализовать механизм обратного вызова

  3. Реализация функций отмены и повтора

  4. Ведение истории команд

java.lang.Thread является хорошей реализацией шаблона Command . Вы можете трактовать Thread как вызывающий и реализующий класс Runnable как ConcreteCommonad / Receiver и run() как Command .

Отменить / Повторить версию шаблона команды можно прочитать на Теодор Норвелл статья

Стратегия:

Шаблон стратегии очень прост для понимания. Используйте этот шаблон, когда

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

Возьмите пример Тарифный компонент системы бронирования авиакомпании

Авиакомпании хотели бы предлагать разные тарифы в разные периоды времени - пиковые и непиковые месяцы. В дни непиковых поездок компания хотела бы стимулировать спрос, предлагая привлекательные скидки.

Ключевые выводы Стратегия шаблон:

  1. Это поведенческий паттерн
  2. Он основан на делегировании
  3. Изменяет внутренности объекта, изменяя поведение метода
  4. Используется для переключения между семейством алгоритмов
  5. Изменяет поведение объекта во время выполнения

Похожие посты с примерами кода:

Использование шаблона проектирования команд

Пример модели стратегии в реальном мире

0 голосов
/ 05 февраля 2016

Для меня разница в намерениях.Реализации обоих шаблонов довольно похожи, но имеют разные цели:

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

  • Для команды компонент, использующий объект, знаетни что команда делает, ни как она это делает - она ​​просто знает, как ее вызвать.Задача вызывающей стороны - просто выполнить команду - обработка, выполняемая Командой, не является частью основной работы вызывающей стороны.

В этом отличие - объект используеткомпонент на самом деле знает или заботится о том, что делает компонент?В большинстве случаев это может быть определено на основе того, возвращает ли объект шаблона значение своему вызывающему.Если вызывающий заботится о том, что делает объект шаблона, он, вероятно, захочет, чтобы он что-то возвращал, и это будет Стратегия.Если он не заботится о каком-либо возвращаемом значении, он, вероятно, является Командой (обратите внимание, что-то вроде Java Callable по-прежнему является Командой, потому что, хотя он и возвращает значение, вызывающий не заботится о значении - он просто передает его обратнок тому, что изначально поставляло Команду).

...