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

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

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

Состояние

Люди поступают по-разному в зависимости от настроения, в котором они находятся. Если вы счастливы, вы делаете многое иначе, чем когда вы грустите или подавлены. Попробуем смоделировать это в коде. Есть класс Person, который представляет реального человека. Наш человек может представиться, получить оскорбление или обнять. Оскорбление злит его, а объятия делают его счастливее - действительно, пример из реальной жизни.

У нас есть три возможных настроения, которые имеют один и тот же интерфейс.

Наш человек может быть счастлив. Тогда он очень милый и говорит хорошие вещи.

Он также может быть в нейтральном настроении. Тогда вы сможете сделать его счастливее, обняв его, или рассердив оскорблением.

Последнее возможное настроение - гнев.

Большой. Давайте посмотрим на наше приложение в действии и на то, как Ян будет себя вести.

Размышляя об использовании шаблонов проектирования, важно рассмотреть альтернативные способы достижения того же поведения. Мы могли бы:

  1. Включите ifs, изменяя ответы в методах Person в зависимости от его состояния
  2. Создавайте специальные классы, такие как 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 может быть очень полезным для готовности вашего кода и сделать его более гибким. Они оба решительно поддерживают принципы единой ответственности и открытого-закрытого. Они перемещают логику, относящуюся к определенной части приложения, в отдельные иерархии и делают добавление новых альтернатив простым и независимым от реализации клиента.

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

Полный исходный код и описание некоторых других паттернов доступны здесь:



Если вы хотите изучить еще несколько полезных шаблонов проектирования, вы можете найти их в следующих статьях: