使用Stateless进行基本状态机设置

21

我有一些相对简单的状态需求(目前)。我想使用Stateless api来建模这些需求。(但是我对状态机的了解不多,所以可能是错误的。)

但是我被术语(特别是StateTrigger)所困扰。

这里有一个例子:我有一个订单类。它设置了几个状态。它们是:New、Filled、Shipping、Completed、Cancelled。

我想要一些简单的状态规则,这些状态转换是被允许的:

  • New(默认状态)
  • New -> Filled
  • New -> Cancelled
  • Filled -> Shipping
  • Filled -> Cancelled
  • Filled -> Shipping
  • Shipping -> Complete

所以我在这里纠结的是我的“触发器”是什么?

以防需要更具体的示例,假设我想要一个像这样的方法:

public bool UpdateOrderStatus(int OrderId, OrderStatusEnum NewOrderStatus)

如果状态更新成功,将返回true。如何设置和使用Stateless使这成为可能?


4
谢谢你挖掘出《无国籍》这部作品,我以前没有看过它。 - kenny
1个回答

34
机器每次只处于一个状态;在任何给定时间,它所处的状态称为当前状态。当由触发事件或条件引发时,它可以从一种状态转换到另一种状态,这称为转换。来自维基上的有限状态机 我认为,触发器就是这个触发事件。更新:当然,触发器名称有时可能等于某些状态名称。
New (initial state)
New -> Filled (trigger "Filled")
New -> Cancelled (trigger "Cancelled")
Filled -> Shipping (trigger "ToBeShipped")
Filled -> Cancelled (trigger "Cancelled")
Shipping -> Complete (trigger "Completed").

更新:

stateless是一个非常好的框架!我已经尝试实现了它的功能。

状态:

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 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);

@Vaccano - 你还没有给我们列出触发器。例如,什么动作会导致“新建”->“已填写”之间的转换?什么动作会导致“新建”->“取消”之间的转换? 我相信这些将是你的触发器。看起来你没有告诉状态机执行哪个状态转换。你只是定义了触发器来引起状态转换,然后在出现触发器时触发,状态机将执行状态转换。 - mbeckish
@mbeckish - 感谢您的评论。看起来状态机并不适合我。我将拥有一个WCF服务调用来触发此状态转换。(即ShipOrders(List<int> orderIds)) 我不知道如何将其转化为对象。 - Vaccano
@Serge - 谢谢你的答复!我另外有一个问题分散了我的注意力一天左右。等我能够回过头来看代码时,我会检查它(如果它有效的话)并接受它。再次感谢! - Vaccano
@Serge - 很棒的答案,不确定为什么还没有被接受,但是对我帮助很大...谢谢! - swannee
@swannee,很高兴它对你有用。 - Sergey Vyacheslavovich Brunov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接