Вернуться в состояние звонящего?

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

У меня есть ситуация, которую я совершенно не знаю, как ее решить. Допустим, у вас есть 2 состояния (ходьба и бег), и они оба могут перейти в третье состояние (прыжок). Как только третье состояние закончено, я хочу вернуться в состояние вызывающего. В некотором смысле, я должен иметь возможность влиять на триггер вызываемого абонента, но это только передается OnEntry и любит, а не само государство.

С помощью EntryFrom кажется, не работает, потому что нет никакого способа повлиять на само состояние "прыжка", только OnEntry функция. С помощью PermitDynamic похоже, тоже не работает, потому что, оказавшись в состоянии "прыжка", я понятия не имею, откуда я.

Я мог бы иметь 2 состояния прыжка (jumpfromrun, jumpfromwalk) с одним OnEntry функция, чтобы минимизировать дубликаты кода. Это то, что я сейчас использую.

Я мог бы сохранить предыдущее состояние во внешней переменной и передать его в мое обновление состояния. Я не хочу делать это (вообще).

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

1 ответ

Решение

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

Вы можете иметь состояние перехода:

stateMachine.Configure(State.Jumping)
    .OnEntry(() => StartJump())
    .OnExit(() => EndJump());

и два подсостояния перехода. Один для ходьбы, один для бега:

stateMachine.Configure(State.WalkJumping)
    .SubstateOf(State.Jumping)
    .Permit(Trigger.DoneJumping, State.Walking);

stateMachine.Configure(State.RunJumping)
    .SubstateOf(State.Jumping)
    .Permit(Trigger.DoneJumping, State.Running);

Затем вы идете и идете по маршруту WalkJumping и RunJumping соответственно.

stateMachine.Configure(State.Walking)
    .OnEntry(() => StartWalking())
    .OnExit(() => EndWalking());
    .Permit(Trigger.Jump, State.WalkJumping);


stateMachine.Configure(State.Running)
    .OnEntry(() => StartRunning())
    .OnExit(() => EndRunning());
    .Permit(Trigger.Jump, State.RunJumping);

Использование таких подложек, в отличие от обычных состояний, дает дополнительное преимущество: State.Jumping может определить то же самое OnEntry а также OnExit это будет наследоваться обоими WalkJumping а также EndJumping,

Кроме того, это дает вам более простой способ проверить, находитесь ли вы в середине прыжка. Вместо:

var state = stateMachine.state;
var isJumping = state == State.WalkJumping || state == RunJumping;

Вы можете просто сделать:

var isJumping = stateMachine.IsInState(State.Jumping);

Который будет правильно учитывать все подсостояния, которые в настоящее время WalkJumping а также RunJumping, Но если вы добавите новое подсостояние перехода в будущем, например, DoubleJumpingтогда isJumping Предикат также автоматически охватит этот случай, не забывая исправлять его.

Другие вопросы по тегам