Шаблон проектирования паттерна

Углубленное обсуждение паттерна государственного проектирования

Паттерн State Design, еще один из наиболее распространенных паттернов дизайна. Он используется, когда мы хотим представить какое-то состояние в нашем приложении.

Что такое паттерн государственного образца?

Паттерн State Design — один из паттернов Behavioral Design, задокументированный Gang of Four (GoF). Этот шаблон тесно связан с конечным автоматом (FSM). Фактически это можно назвать приложением FSM.

Этот шаблон проектирования позволяет изменять поведение в зависимости от изменений его внутреннего состояния.

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

Паттерн State Design следует принципу открытого закрытия принципов SOLID Design (что мы обсудим подробно в будущем). Класс закрыт для изменений, но открыт для расширения.

Паттерн State Design также разделяет код. Он разделяет Where и What в прикладной логике состояний.

Примеры

Я не могу найти пример шаблона State Design в Core Java API. Однако вы можете представить себе всевозможные приложения, требующие некоторого управления состоянием. Так что использование паттерна государственного дизайна довольно распространено. Вы можете подумать о BoomBox. Вы нажимаете кнопку Play, и BoomBox начинает играть. Вы можете нажать кнопку стоп, чтобы остановить воспроизведение.

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

Диаграмма состояний

Как упоминалось выше, паттерн State Design в общих чертах основан на концепции конечного автомата. Автомат легко представить в виде диаграммы состояний.

Диаграмма состояний — это тип диаграммы, используемый в информатике и смежных областях для описания поведения систем.

Диаграмма состояний имеет конечное число состояний Системы. Они представлены кружками или овалами. Стрелки, соединяющие эти состояния, представляют собой переход из одного состояния в другое. Обозначения напротив стрелок — это условие перехода.

См. также:  Приложение Rails с интерфейсом jQuery

Для упомянутого выше примера BoomBox диаграмма состояний может быть нарисована следующим образом:

Реализация конечного автомата

Очень простая реализация конечного автомата выглядит следующим образом:

Чтобы запустить вышеупомянутый класс, мы можем использовать код ниже —

Вывод приведенного выше кода

Присмотритесь к классу BoomBox сверху. Это пример реализации конечного автомата. В этом примере реализуется конечный автомат с тремя состояниями: воспроизведение, пауза и остановка. Чтобы перейти из одного состояния в другое, нам необходимо выполнить несколько проверок. Поскольку не все переходы поддерживаются. например Вы не можете перейти от игры к игре. Забавно, но это правильно. На BoomBox, если вы нажмете кнопку воспроизведения, когда он уже играет, ничего не ожидается. Другой пример ограничения состояния: если BoomBox находится в остановленном состоянии, ничего не произойдет, если вы попытаетесь приостановить его. Диаграмма состояний выше может подтвердить эти ограничения.

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

Зачем нам нужно использовать паттерн государственного проектирования?

  • Сетка операторов if-else. В очень простом конечном автомате, подобном приведенному выше, мы получили сетку операторов if-else. Представьте себе, что у нас есть еще много состояний и много переходов. Охватить все сценарии будет очень сложно. Даже код не читается с помощью такого простого конечного автомата, как этот.
  • Решение не расширяемо — в настоящее время у нас есть только три состояния на нашей машине. Когда мы попытаемся добавить четвертый и пятый, нам придется переоценить наши методы play (), pause () и stop (). Нам нужно убедиться, что охватываются все комбинации. Добавьте еще несколько условий if-else. Вскоре это становится невозможным.
  • Нарушение принципов дизайна. Нарушены такие принципы дизайна, как единственная ответственность и принципы открытого и закрытого типа. В классе BoomBox мы делаем несколько вещей, и мы не можем вводить новые состояния без изменения существующего кода.

Диаграмма UML

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

См. также:  Базовая 2-D игра на Python (часть 4)

Рассмотрим на примере BoomBox. BoomBox может быть нашим классом Context снизу. В интерфейсе состояния есть такие методы, как play (), pause () и stop (). Пауза, воспроизведение и остановка могут быть реализацией интерфейса состояния.

Реализация паттерна государственного проектирования

Мы пытаемся реализовать конечный автомат, как упоминалось выше, с использованием шаблона State Design. Мы сохраним класс BoomBox и изменим его в соответствии с требованиями паттернов State Design. Мы также сохраняем тестовый код в void main как есть. Давайте начнем с представления интерфейса состояния.

Эти методы примерно соответствуют методам в интерфейсе BoomBox. Хотя мы не программировали интерфейс, если бы мы создали интерфейс BoomBox, мы бы нашли там эти методы.

Теперь наш пример BoomBox может находиться в одном из трех состояний — воспроизведение, пауза или остановка. Мы реализуем этот интерфейс в трех классах, представляющих состояния.

Состояние 1: StatePlaying

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

Состояние 2: StatePaused

Состояние 3: StateStopped

Теперь мы изменим класс BoomBox, чтобы учесть изменение состояний. Раньше реализация была основана на статических int, а теперь у нас есть отдельные классы для состояний.

Посмотрите здесь код методов play (), pause () и stop (). Это просто вызов метода с тем же именем для объекта состояния. state содержит текущий объект состояния.

Вначале состояние инициализируется для остановки объекта состояния (stateStop). Когда вызывается метод воспроизведения на BoomBox, он вызывает метод воспроизведения для объекта состояния остановки.

Теперь посмотрим на реализацию метода воспроизведения в StateStopped. Там мы обновляем состояние BoomBox до воспроизведения и регистрируем «воспроизведение». Это может быть реальная логика для игры в BoomBox.

См. также:  iOS | Свифт | Как сохранить пользовательские объекты в UserDefaults с помощью PropertyListEncoder/Decoder с…

А теперь представьте, если мы вызовем метод остановки на BoomBox, и мы уже находимся в состоянии Stopped. Посмотрите на метод stop () в StateStopped. Посмотрите, как мы просто регистрируем сообщение о том, что мы уже находимся в остановленном состоянии. Такая логика является частью реализации, зависящей от состояния.

Проблемы, решаемые паттерном State Design

Паттерн State Design решает две основные проблемы:

  • Объект должен изменить свое поведение при изменении его внутреннего состояния.
  • Поведение, зависящее от состояния, следует определять независимо. То есть добавление новых состояний не должно влиять на поведение существующих состояний.

Проблемы с паттернами государственного проектирования

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

  • Усложняет дизайн. В примере с небольшим конечным автоматом он усложняет дизайн, вводя несколько новых классов. Иногда с этой работой справляются только некоторые int и несколько if. Но если мы используем паттерн состояний, мы можем излишне использовать паттерн State Design.
  • Необходимо знать все состояния. Несмотря на то, что шаблон проектирования состояний достаточно расширяем, чтобы учесть все большее количество состояний, всегда полезно провести надлежащую проработку на этапе проектирования и определить все возможные состояния перед приступаем к реализации.
  • Класс маршрутизации. Класс контекста, как в нашем случае, класс BoomBox становится простым классом маршрутизации без какой-либо собственной логики. Вся логика находится в классах, зависящих от состояния.

Резюме

  • Реализация государственной машины
  • Допускает различное поведение в зависимости от внутренних состояний
  • Очень легко добавить новое состояние — расширяемые состояния
  • Упрощает спагетти-код, снижает цикломатическую сложность
  • Вовлечено большое количество небольших классов

Написал и отредактировал — Вивек Миттал

Вивек Миттал — главный инженер-программист — Nuance Communications | LinkedIn
Я опытный инженер-программист с более чем 10-летним опытом разработки программного обеспечения. У меня есть обширный… www.linkedin.com

Дополнительное чтение

Шаблоны проектирования программного обеспечения
Обзор шаблонов проектирования программного обеспечения medium.com

Шаблон дизайна — Синглтон
Подробное обсуждение наиболее распространенного шаблона дизайна — Синглтон medium.com

Шаблон дизайна — Builder
Подробное обсуждение шаблона дизайна Builder medium.com

Понравилась статья? Поделиться с друзьями:
IT Шеф
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: