Базовая настройка конечного автомата с использованием Stateless - PullRequest
19 голосов
/ 02 февраля 2012

У меня есть довольно простые государственные потребности (на данный момент). Я думаю, что хотел бы смоделировать их, используя Stateless api. (Но я мало что знаю о конечных автоматах, поэтому могу ошибаться.)

Но я попадаю в терминологию (в частности Состояние и Триггер )

Вот пример: у меня есть класс заказа. Это настроено с несколькими состояниями. Это: Новый, Заполненный, Отгрузка, Завершенный, Отмененный.

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

  • Новый (по умолчанию)
  • Новый -> Заполненный
  • Новое -> Отменено
  • Заполнено -> Доставка
  • Заполнено -> Отменено
  • Заполнено -> Доставка
  • Доставка -> Завершено

Так, где меня тут спотыкают, каков мой "Триггер"?

На всякий случай, если нужен более конкретный пример, скажем, я хочу такой метод:

public bool UpdateOrderStatus(int OrderId, OrderStatusEnum NewOrderStatus)

, который вернет true, если статус обновлен успешно. Как можно настроить и использовать Stateless, чтобы это произошло?

1 Ответ

27 голосов
/ 02 февраля 2012

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

Полагаю, триггер - это событие запуска .

Обновление:

Конечно, имя триггера иногда может совпадать с некоторыми именами состояний.

New (initial state)
New -> Filled (trigger "Filled")
New -> Cancelled (trigger "Cancelled")
Filled -> Shipping (trigger "ToBeShipped")
Filled -> Cancelled (trigger "Cancelled")
Shipping -> Complete (trigger "Completed").

Обновление:

Stateless - это действительно хорошая структура! Я пытался реализовать функциональность.

States:

public enum State
{
    New,
    Filled,
    Shipping,
    Cancelled,
    Completed
}

Триггеры:

public enum Trigger
{
    Filled,
    Cancelled,
    ToBeShipped,
    Completed
}

Класс заказа:

public class Order
{
    private readonly StateMachine<State, Trigger> _stateMachine;

    public Order()
    {
        _stateMachine = CreateStateMachine();
    }

    public bool TryUpdateOrderStatus(Trigger trigger)
    {
        if (!_stateMachine.CanFire(trigger))
            return false;

        _stateMachine.Fire(trigger);
        return true;
    }

    public State Status
    {
        get
        {
            return _stateMachine.State;
        }
    }

    private StateMachine<State, Trigger> CreateStateMachine()
    {
        StateMachine<State, Trigger> stateMachine = new StateMachine<State, Trigger>(State.New);
        stateMachine.Configure(State.New)
            .Permit(Trigger.Filled, State.Filled)
            .Permit(Trigger.Cancelled, State.Cancelled);

        stateMachine.Configure(State.Filled)
            .Permit(Trigger.ToBeShipped, State.Shipping)
            .Permit(Trigger.Cancelled, State.Cancelled);

        stateMachine.Configure(State.Shipping)
            .Permit(Trigger.Completed, State.Completed);

        stateMachine.OnUnhandledTrigger((state, trigger) =>
            {
                Console.WriteLine("Unhandled: '{0}' state, '{1}' trigger!");
            });
        return stateMachine;
    }
}

Тестер для класса заказа:

Order order = new Order();
bool result = order.TryUpdateOrderStatus(Trigger.Completed);
Console.WriteLine("Attemp to complete order: {0}", result);
Console.WriteLine("Order status: {0}", order.Status);

result = order.TryUpdateOrderStatus(Trigger.ToBeShipped);
Console.WriteLine("Attemp to ship order: {0}", result);
Console.WriteLine("Order status: {0}", order.Status);

result = order.TryUpdateOrderStatus(Trigger.Cancelled);
Console.WriteLine("Attemp to cancel order: {0}", result);
Console.WriteLine("Order status: {0}", order.Status);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...