Конечный автомат: как изменить состояние без внешнего события (переходное состояние)?

Сценарий:
У меня есть простой конечный автомат:

Удачный путь:

Uninitialized->Initialized->InProgress->Done

Несчастливый путь:

Uninitialized->Initialized->Error

Проще говоря, мне нужно вызвать переход (либо в состояние InProgress, либо в состояние ошибки) без внешнего события / триггера. Т.е. Инициализированное состояние должно немедленно привести к одному из этих состояний.

Вопросов:

  1. Можно ли вызвать переход состояния из Initialized.Enter ()?
  2. Я мог бы использовать государственную охрану для этого, но я бы предпочел не иметь нетривиальной логики в государственной охране (а инициализация вполне может быть сложной).
  3. Если это НЕ ОК, как я могу сделать это по-другому?
  4. Должен ли я просто вынести это решение из конечного автомата и заставить какой-либо другой компонент вызвать соответствующий переход? Но тогда разве мне не придется вызывать этот внешний компонент из Initialized.Enter ()? так это ничего не решает?

person THX-1138    schedule 19.05.2009    source источник
comment
связанные: stackoverflow.com/questions/1647631/c-state- машиностроение /   -  person jldupont    schedule 31.10.2009


Ответы (1)


В конечном автомате следующее состояние является комбинаторной логической функцией как входного, так и текущего состояния.

В случае, который вы описываете, одна и та же причина (состояние Initialized) может вызвать два разных эффекта (состояние InProgress или Error). Я предполагаю, что есть скрытый ввод, значение которого имеет значение. Я также предполагаю, что этот ввод получен при переходе с Uninitialized на Initialized.

Поэтому у меня была бы другая модель:

Uninitialized -> Successfully initialized -> InProgress -> Done
             \
              `-> Failed Initialization -> Error

Возможно сочетание Successfully initialized с InProgress и Failed initialization с Error.


РЕДАКТИРОВАТЬ: из вашего комментария я понимаю, что скрытый ввод на самом деле является результатом действия (инициализации устройства). Взяв вашу модель, я предполагаю, что инициализация происходит в состоянии Initialized (назовем его Initializing). Таким образом, результатом устройства будет ваше внешнее событие, которое вызовет переход либо к InProgress, либо к Error.

Так что оставьте свой конечный автомат и просто добавьте результат device.Initialize() в список входов или внешних событий.

person mouviciel    schedule 19.05.2009