当前位置: 首页 > news >正文

C#中状态机Stateless初使用

参考文献:.net轻量状态机Stateless

一、Stateless介绍

        Stateless是一个轻量级、高性能的状态机库,可用在.net应用程序中实现状态流的变化,能够轻松地帮助我们实现状态转换的逻辑。

状态机:"依照指定的状态流程图,根据当前执行的动作,将当前状态按照预定的条件变更到新的状态 "。状态机有4个要素,即现态、条件、动作、次态。其中,现态和条件是“因”, 动作和次态是“果”。

  • 现态 - 是指当前对象的状态
  • 条件 - 当一个条件满足时,当前对象会触发一个动作
  • 动作 - 条件满足之后,执行的动作
  • 次态 - 条件满足之后,当前对象的新状态。次态是相对现态而言的,次态一旦触发,就变成了现态

状态迁移图:用来描述一个特定的对象所有可能的状态,以及由于各种事件的发生而引起的状态之间的转移和变化,也是配置状态机按照何种行径的前提 。

二、Stateless的使用

根据上面的状态迁移图,实现状态流变化的Demo。

1、梳理状态流中每个节点的走向和触发动作

如上图。

2、安装 Stateless 库

我这里安装的是这个。

3、定义状态和触发事件

 订单状态

/// <summary>
/// 订单状态
/// </summary>
internal enum OrderState
{
    /// <summary>
    /// 创建
    /// </summary>
    OrderCreate=0,

    /// <summary>
    /// 关闭
    /// </summary>
    Invalided=1,

    /// <summary>
    /// 待支付
    /// </summary>
    PendingSign=2,

    /// <summary>
    /// 待发货
    /// </summary>
    PendingSend=3,

    /// <summary>
    /// 待收货
    /// </summary>
    PendingReceipt=4,

    /// <summary>
    /// 待退款
    /// </summary>
    PendingRefund=5,

    /// <summary>
    /// 完成
    /// </summary>
    Completed=6,
}

 订单状态的触发事件

/// <summary>
/// 订单状态触发事件
/// </summary>
internal enum OrderTrigger
{
    /// <summary>
    /// 跳转
    /// </summary>
    Jump=0,

    /// <summary>
    /// 取消
    /// </summary>
    Cancel=1,

    /// <summary>
    /// 支付
    /// </summary>
    Payment=2,

    /// <summary>
    /// 配送
    /// </summary>
    Send=3,

    /// <summary>
    /// 签收
    /// </summary>
    Sign=4,

    /// <summary>
    /// 退款
    /// </summary>
    Refund=5,
}

4、实现状态机

根据上面状态流程配置状态机 Stateless,给每个状态节点配置状态转换规则。

internal class OrderStateMachine
{
    private readonly StateMachine<OrderState, OrderTrigger> _stateMachine;
    public OrderStateMachine(OrderState orderState)
    {
        //因为 Stateless的状态可能来自ORM 等外部环境,所以初始化状态机时接收一个来自外界的状态 orderState 作为当前状态
        _stateMachine = new StateMachine<OrderState, OrderTrigger>(orderState);
        ConfigureStateMachine();
    }
    /// <summary>
    /// 配置流程
    /// </summary>
    private void ConfigureStateMachine()
    {
         //订单 => 待支付
         _stateMachine.Configure(OrderState.OrderCreate)
            .Permit(OrderTrigger.Jump, OrderState.PendingSign)
            .Permit(OrderTrigger.Cancel,OrderState.Invalided);
         // 待支付 => 代发货/关闭
         _stateMachine.Configure(OrderState.PendingSign)
             .Permit(OrderTrigger.Payment, OrderState.PendingSend)
             .Permit(OrderTrigger.Cancel, OrderState.Invalided);
         // 代发货 => 待收货/待退款
         _stateMachine.Configure(OrderState.PendingSend)
             .Permit(OrderTrigger.Send, OrderState.PendingReceipt)
             .Permit(OrderTrigger.Cancel,OrderState.PendingRefund);
         // 待退款 => 关闭
         _stateMachine.Configure(OrderState.PendingRefund)
             .Permit(OrderTrigger.Refund, OrderState.Invalided);
         // 待收货 => 完成
         _stateMachine.Configure(OrderState.PendingReceipt)
             .Permit(OrderTrigger.Sign, OrderState.Completed);
        }
    /// <summary>
    /// 获取当前状态的方法
    /// </summary>
    public StateMachine<OrderState, OrderTrigger> GetStateMachine()
    {
        return _stateMachine;
    }
}

5、状态机的使用

        在使用 Fire() 触发状态变换时,如果当前节点没有配置这个触发事件Trigger,则会抛出一个异常。可以在状态转换前,使用 CanFire() 方法来判断配置流程中是否有这个触发事件Trigger,有才让它触发状态转换,也可以使用Ignore方法,忽视一些触发,当触发了此类触发器时,不会抛出异常,而改为忽略该次触发。

状态机调用器:

internal class StateMachineInvoker
{
   private readonly OrderStateMachine _stateMachine;
   public StateMachineInvoker(OrderStateMachine stateMachine)
   {
        _stateMachine = stateMachine;
   }
   public bool UpdateOrderState(OrderTrigger trigger, out OrderState orderState)
   {
        bool flag;
        var machine = _stateMachine.GetStateMachine();
        try
        {
            Console.WriteLine($"修改前的状态为: {machine.State}");
            if (machine.CanFire(trigger))
            {
                // 状态变换,状态变换至 trigger 态
                machine.Fire(trigger);
                // 此时状态已经发生了变换,下一个状态成立当前状态
                Console.WriteLine($"当前状态为: {machine.State}"); 
                if (machine.State == OrderState.Invalided)
                {
                    flag = false;
                }
                else 
                { 
                    flag = true;
                 }
            }
            else
            {
                Console.WriteLine($"与Stateless配置流冲突,不能由 {machine.State} 状态直接变换到 {trigger} 状态。");
                flag = false;
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"错误: {e.Message}");
            flag = false;
        }
        orderState = machine.State;
        return flag;
    }
}

2、使用状态机

internal class Program
{
    static void Main(string[] args)
    {
        OrderState orderState = OrderState.OrderCreate;
        var b = GetTrigger(ref orderState,out int numTrigger, out OrderState newOrderState);
        while (b)
        {
            b = GetTrigger(ref newOrderState, out numTrigger, out newOrderState);
        }
        Console.WriteLine("结束");
        Console.ReadKey();
    }
    public static bool GetTrigger(ref OrderState orderState,out int numTrigger, out OrderState newOrderState)
    {
        while (true)
        {
            Console.WriteLine($"请输入对订单状态的操作://n Jump: 0、Cancel: 1、Payment:2、Send: 3、Sign: 4、Refund: 5");
            numTrigger = Convert.ToInt32(Console.ReadLine());
            if (numTrigger >= 0 && numTrigger < 7)
            {
                break;
            }
        }
        // 初始化状态机
        OrderStateMachine stateMachine = new OrderStateMachine(orderState);
        // 初始化状态机调用器
        StateMachineInvoker stateMachineInvoker = new StateMachineInvoker(stateMachine);
        var flag =  stateMachineInvoker.UpdateOrderState((OrderTrigger)numTrigger,out newOrderState);
        return flag;
    }
}


好记性不如烂笔头,在学习的路上留下点痕迹。希望能给大家带来帮助,也期待你的点赞和平路。

若有不足之处,还请斧正。

相关文章:

  • JAVA 对象序列化和反序列化
  • DataX 3.0详解
  • 开源项目利用browser-use-webui和DeepSeek把浏览器打造成一个AI Agent智能体!
  • deepseek日常用法的核心原则
  • android Kotlin原理
  • CentOS7系统更新yum源教程
  • Axios企业级封装实战:从拦截器到安全策略!!!
  • paddle ocr
  • 鸿蒙学习笔记(3)-像素单位、this指向问题、RelativeContainer布局、@Style装饰器和@Extend装饰器
  • Flutter入门教程:从零开始的Flutter开发指南
  • C++11中引入的比较常用的新特性讲解(下)
  • Android设计模式之观察者模式
  • 【IntelliJ IDEA导出WAR包教程】
  • 设计模式-领域模式
  • 享元模式介绍
  • Flutter完整开发实战详解(一、Dart语言和Flutter基础)
  • 当Kafka化身抽水马桶:论组件并发提升与系统可用性的量子纠缠关系
  • Css环形旋转立体感动画
  • 【GNN】第五章:图神经网络架构中的基础设施——GCN、GAT、GraphSAGE、TopKPooling、GAP、GMP
  • AWTK-WEB 快速入门(6) - JS WebSocket 应用程序
  • ubuntu17 wordpress/唐山百度搜索排名优化
  • 2022年没封网站直接进入/电商网站制作
  • 广告点击网站源码/网络营销岗位技能
  • 公司是否可以做多个网站/搜索优化是什么意思
  • 个人网站备案后做游戏/北京seo排名优化网站
  • 找外包公司做网站价钱/seo好seo