Состояние и Стратегия - очень популярные и полезные шаблоны проектирования, которые могут помочь вам лучше организовать код.
Состояние и Стратегия очень похожи по реализации, но различаются по мотивам. В шаблоне состояния объект меняет свое поведение в зависимости от внутреннего состояния, в котором он находится. В случае стратегии поведение объекта зависит от предоставленного алгоритма. В обоих случаях использования используемые состояния и алгоритмы инкапсулируются в отдельные классы.
Состояние и Стратегия - это модели поведения. Паттерны поведенческого проектирования ориентированы на общение и разделение ответственности между объектами.
Состояние
Люди поступают по-разному в зависимости от настроения, в котором они находятся. Если вы счастливы, вы делаете многое иначе, чем когда вы грустите или подавлены. Попробуем смоделировать это в коде. Есть класс Person
, который представляет реального человека. Наш человек может представиться, получить оскорбление или обнять. Оскорбление злит его, а объятия делают его счастливее - действительно, пример из реальной жизни.
У нас есть три возможных настроения, которые имеют один и тот же интерфейс.
Наш человек может быть счастлив. Тогда он очень милый и говорит хорошие вещи.
Он также может быть в нейтральном настроении. Тогда вы сможете сделать его счастливее, обняв его, или рассердив оскорблением.
Последнее возможное настроение - гнев.
Большой. Давайте посмотрим на наше приложение в действии и на то, как Ян будет себя вести.
Размышляя об использовании шаблонов проектирования, важно рассмотреть альтернативные способы достижения того же поведения. Мы могли бы:
- Включите ifs, изменяя ответы в методах
Person
в зависимости от его состояния - Создавайте специальные классы, такие как
AngryPerson
,NeutralPerson
,HappyPerson
Мы бы столкнулись с ненужной сложностью или дублированием кода, если бы попробовали Решения 1 или 2. По сравнению с шаблоном состояния они оба могут стать нечитаемыми и плохо масштабироваться.
Паттерн состояния состоит из трех элементов:
- Контекст (_6 _) - использует состояния и определяет интерфейс для клиентов.
- Состояние (_7 _) - интерфейс каждого состояния
- Конкретное состояние (
Happy
,Neutral
, _10 _) - реализация состояния
В этом шаблоне состояние объекта может быть изменено в двух местах: в контексте или в конкретном состоянии. Оба подхода хороши, и это зависит от конкретного случая, какой из них мы должны использовать.
Популярные примеры использования паттерна State:
- система конференц-залов (комнаты в состояниях: свободные, занятые и т. д.)
- производственный цикл (продукция находится в состояниях: готов к сборке, в работе, готов к отгрузке, отгружен и т. д.)
- цикл утверждения (книги находятся в состояниях: новые, утвержденные, опубликованные)
- лампочки (они в состояниях: включены или выключены)
Стратегия
Этот шаблон проектирования фокусируется на отделении используемого алгоритма от клиента. Мы хотим передать некоторые данные из массива в JSON, XML или строку, разделенную запятыми. В каждом случае мы должны обрабатывать данные по-разному и выдавать результат в виде строки. Использование этого компонента должно быть максимально простым. Мы могли бы предоставить экземпляр конкретной стратегии __construct
нашего контекста или ключа, представляющего выбранный алгоритм. Пока мы воспользуемся вторым вариантом.
Каждый алгоритм должен иметь общий интерфейс.
Сгенерировать JSON из массива в PHP очень просто. Все, что нам нужно сделать, это вызвать json_encode
по данным.
Преобразование массива в строку, разделенную запятыми, тоже не очень сложно.
Самым сложным было создать XML-строку из заданных данных. Нам удалось это сделать с использованием SimpleXMLElement
.
Теперь преобразование данных стало намного проще. Добавление дополнительных форматов теперь было бы проще простого.
Шаблон стратегии состоит из трех элементов:
- Контекст (_14 _) - использует конкретные стратегии и определяет интерфейс для клиентов.
- Стратегия (_15 _) - интерфейс для используемых алгоритмов
- Конкретная стратегия (
JSONFormatter
,XMLFormatter
,StringFormatter
) - реализация алгоритмов
Популярные примеры использования паттерна Стратегия:
- использование алгоритма сортировки (каждый алгоритм находится в отдельной стратегии).
- форматирование текста (каждый метод форматирования текста - это отдельная стратегия).
- разные подходы к проблеме (например, разные алгоритмы задачи коммивояжера, представленные каждой стратегией).
- использование разных алгоритмов в зависимости от заданных условий (например, отображение другого маршрута к месту в зависимости от режима связи и погодных условий или использование разных способов оплаты, таких как кредитная карта и PayPal).
Заключение
Использование State и Strategy может быть очень полезным для готовности вашего кода и сделать его более гибким. Они оба решительно поддерживают принципы единой ответственности и открытого-закрытого. Они перемещают логику, относящуюся к определенной части приложения, в отдельные иерархии и делают добавление новых альтернатив простым и независимым от реализации клиента.
Тем не менее, использование таких шаблонов также может иногда чрезмерно усложнять ваш код. Если в коде всего несколько состояний или стратегий или они меняются очень редко, это может быть просто излишним. Помните, что эти модели не являются окончательными лекарствами.
Полный исходный код и описание некоторых других паттернов доступны здесь:
Если вы хотите изучить еще несколько полезных шаблонов проектирования, вы можете найти их в следующих статьях:
- Заводской метод
- Творческие узоры
- Итератор
- Итератор
- Шаблонный метод
- Наилегчайший вес
- Прокси
- Декоратор
- "Внедрение зависимости"
- Композитный
- Адаптер
- "Фасад"
- "Мост"
- Цепочка ответственности
- Посетитель
- Команда
- Нулевой объект
- Свободный интерфейс
- "Технические характеристики"