Кто-нибудь может объяснить, пожалуйста, в терминах непрофессионала?
Шаблоны проектирования на самом деле не являются "непрофессиональными" понятиями, но я постараюсь сделать их как можно более понятными. Любой шаблон дизайна можно рассматривать в трех измерениях:
- Проблема, которую решает шаблон;
- Статическая структура шаблона (диаграмма классов);
- Динамика паттерна (диаграммы последовательности).
Давайте сравним состояние и стратегию.
Проблема, которую решает шаблон
State используется в одном из двух случаев [GoF book p. 306]
- Поведение объекта зависит от его состояния, и оно должно изменить свое поведение во время выполнения в зависимости от этого состояния.
- Операции имеют большие составные условные операторы, которые зависят от
состояние объекта. Это состояние обычно представлено одним или несколькими перечисленными
константы. Часто несколько операций будут содержать одну и ту же условную структуру. Шаблон State помещает каждую ветвь условия в отдельный класс. Это позволяет трактовать состояние объекта как отдельного объекта, который может отличаться независимо от других объектов.
Если вы хотите убедиться, что у вас действительно есть проблема, решаемая шаблоном State, вы должны иметь возможность моделировать состояния объекта, используя конечный автомат . Вы можете найти пример применения здесь .
Каждый переход состояния является методом в интерфейсе состояния. Это подразумевает, что для дизайна вы должны быть достаточно уверены в переходах между состояниями, прежде чем применять этот шаблон. В противном случае, если вы добавите или удалите переходы, это потребует изменения интерфейса и всех классов, которые его реализуют.
Лично я не нашел этот образец таким полезным. Вы всегда можете реализовать конечные автоматы, используя таблицу поиска (это не OO-способ, но он работает довольно хорошо).
Стратегия используется для следующих [GoF book p. 316]
- многие связанные классы отличаются только своим поведением. Стратегии предоставляют способ настроить класс с одним из многих вариантов поведения.
- вам нужны разные варианты алгоритма. Например, вы можете определить алгоритмы, отражающие различные компромиссы пространства / времени. Стратегии могут использоваться, когда эти варианты реализованы в виде иерархии классов алгоритмов [HO87].
- алгоритм использует данные, о которых клиенты не должны знать. Используйте шаблон «Стратегия», чтобы избежать выявления сложных, специфичных для алгоритма структур данных.
- класс определяет много поведений, и они появляются как несколько условных операторов в своих операциях. Вместо многих условных выражений переместите соответствующие условные ветви в свой собственный класс Стратегии.
Последний случай применения Стратегии связан с рефакторингом, известным как Замените условный полиморфизм .
Краткое содержание: Состояние и стратегия решают самые разные задачи. Если ваша проблема не может быть смоделирована с помощью конечного автомата, то, скорее всего, шаблон State не подходит. Если ваша проблема не в инкапсуляции вариантов сложного алгоритма, тогда Стратегия не применяется.
Статическая структура рисунка
Состояние имеет следующую структуру классов UML:
Стратегия имеет следующую структуру классов UML:
Резюме: с точки зрения статической структуры, эти две модели в основном идентичны. На самом деле, инструменты обнаружения шаблонов, такие как , этот считают, что " структура
[...] шаблоны идентичны, запрещая их
различение автоматическим процессом (например, без ссылки
к концептуальной информации)."
Однако может быть существенное отличие, если ConcreteStates решат сами переходы между состояниями (см. « может определять » ассоциации на диаграмме выше). Это приводит к связи между конкретными состояниями. Например (см. Следующий раздел), состояние A определяет переход в состояние B. Если класс Context принимает решение о переходе в следующее конкретное состояние, эти зависимости исчезают.
Динамика выкройки
Как упоминалось выше в разделе «Проблема», State подразумевает, что поведение изменяется во время выполнения в зависимости от некоторого состояния объекта. Следовательно, применяется понятие состояния переходного , как обсуждалось с отношением конечного автомата . [GoF] упоминает, что переходы могут быть определены либо в подклассах ConcreteState, либо в централизованном расположении (например, в расположении на основе таблицы).
Давайте предположим простой конечный автомат:
Предполагая, что подклассы решают переход состояния (возвращая следующий объект состояния), динамика выглядит примерно так:
Чтобы показать динамику Стратегии , полезно позаимствовать реальный пример .
Сводка : Каждый шаблон использует полиморфный вызов, чтобы сделать что-то в зависимости от контекста. В паттерне State полиморфный вызов (переход) часто вызывает изменение следующего состояния . В паттерне Стратегия полиморфный вызов обычно не меняет контекст (например, оплата кредитной картой один раз не означает, что вы будете платить PayPal в следующий раз). Опять же, динамика паттерна состояний определяется соответствующим ему конечным автоматом , , который (для меня) необходим для правильного применения этого паттерна.