В чем разница между конечным автоматом и реализацией шаблона состояния?

Интересно, конечный автомат - это просто шаблон состояния на работе или есть разница между этими двумя?

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

7 ответов

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

Хотя статья на самом деле была хорошо прочитана, я не согласен с автором по нескольким пунктам:

  • "Больше нет причин использовать конечные автоматы, когда вы используете объектно-ориентированный язык программирования", это категорически неверно, если у вас есть какие-либо требования к скорости выполнения.
  • Идея о том, что реализация авторов является особенно короткой или простой, или что она требует меньшего технического обслуживания, чем цифровая фотокамера с улучшенными состояниями, зависит от вашего варианта использования и личного вкуса, но не может быть названа катастрофически. http://www.boost.org/doc/libs/1_55_0/libs/statechart/doc/tutorial.html

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

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

С точки зрения обслуживания следует отметить, что регистрация необработанных событий не может быть выполнена из одного центрального суперсостояния с шаблоном состояния. Также добавление новой функции типа события / обработчика требует добавления функции ко всем состояниям! Я не считаю, что техническое обслуживание дружелюбно.

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

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

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

В случае, если кто-то еще заинтересован, вот мое мнение:

В конечном автомате объект может находиться в разных состояниях, но нам все равно, как они себя ведут в этих состояниях. На самом деле, нас интересует, какое действие применяется, когда объект переходит в следующее состояние. Если вы реализуете конечный автомат в Java, состояние будет просто перечислением или String, и будет класс Transition с методом doAction().

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

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

Но для варианта использования, например, для заказа онлайн-продуктов, когда вам все равно, как ведет себя объект заказа. Вам важно только, если заказ находится в состоянии "add_to_cart", когда публикуется событие "payment_finished", а затем измените его на состояние "обработка". В этом случае состояние является простым свойством перечисления класса Order, поэтому использование конечного автомата намного лучше.

Конечный автомат может быть спроектирован и реализован несколькими способами. Одним из способов является использование паттерна состояния, описанного в книге "Банды четырех". Но есть и другие способы реализации конечного автомата.

Например, вы можете захотеть взглянуть на исследование Миро Самека, прочитав книгу Практические диаграммы состояний UML на C/C++, 2-е изд. (Событийное программирование для встроенных систем)

Вы также можете найти интересным этот вопрос.

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

Вот пример Kotlin:

     inner class StateContext : State {

       private var stateContext: State? = null
       private var lockState: Boolean = false

       fun isLockState(): Boolean {
           return lockState
       }

       fun setLockState(lockState: Boolean): StateContext {
           this.lockState = lockState//no further actions allowed. useful if you need to permenatley lock out the user from changing state.
           return this
       }

       fun getState(): State? {
           return this.stateContext
       }

       fun setState(state: State): StateContext {
           if (!lockState) this.stateContext = state
           return this
       }

       override fun doAction() {
           this.stateContext?.doAction()
       }
   }

с конечным автоматом я не уверен, как это будет сделано легко.

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

Я написал статью о паттерне государственного проектирования и конечных автоматах: https://medium.com/@1gravityllc/the-super-state-design-pattern-166127ce7c9a. В статье я показываю, что их направленность различна, но они также не исключают друг друга. Есть способ объединить их, чтобы получить шаблон проектирования суперсостояния.

Основное внимание в шаблоне проектирования состояний уделяется инкапсуляции поведения для создания повторно используемых и обслуживаемых компонентов (состояний).

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

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

конечный автомат - это просто шаблон состояния на работе или, если есть разница между этими двумя

TL;DR: представьте, что вам нужно заменить состояние другим. Затем представьте, что вам нужно добавить новое состояние.

Полный ответ. Существует большая разница.

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

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

Прочитав так много ответов, я понимаю следующее:

  • Конечный автомат — это математический/технический термин. Математическая модель, описывающая состояние и переходы состояний компьютера, такого как торговый автомат или стиральная машина, представлена ​​в виде диаграммы состояний

  • Шаблоны состояний — это имя программирования. Шаблон проектирования заключается в том, чтобы лучше стандартизировать структуру дизайна кода, чтобы облегчить инкапсуляцию, повторное использование, простоту расширения; Режим состояния используется для решения проблемы, связанной с тем, что объекты ведут себя по-разному в зависимости от своего состояния.

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