2026/4/18 11:43:01
网站建设
项目流程
本地wordpress后台,上海百度seo,国内优秀html网站,做网站大记事代码一、状态机的核心概念1. 什么是状态机#xff1f;状态机#xff08;Finite State Machine, FSM#xff0c;又称有限状态机#xff09; 是一种数学模型和编程思想#xff0c;用于描述一个对象#xff08;或系统#xff09;在其生命周期内的有限个状态#xff0c;以及这些…一、状态机的核心概念1. 什么是状态机状态机Finite State Machine, FSM又称有限状态机是一种数学模型和编程思想用于描述一个对象或系统在其生命周期内的有限个状态以及这些状态之间的转移规则、触发转移的事件 / 条件还有状态转移过程中或处于某个状态时需要执行的动作 / 行为。简单理解它就像对象的 “行为剧本”规定了对象在什么状态下遇到什么事情应该切换到什么新状态同时要做什么事。2. 状态机的核心组成要素一个完整的有限状态机包含 4 个核心部分缺一不可状态State对象的离散状态数量有限。例如 “电梯停止”“电梯上行”“电梯下行”“订单待支付”“订单已支付”“订单已取消”。事件Event/Trigger触发状态转移的外部或内部条件 / 信号。例如 “乘客按下 5 楼按钮”触发电梯上行、“用户完成支付”触发订单从待支付→已支付。转移Transition从一个状态切换到另一个状态的规则通常是 “当前状态 事件→目标状态”。例如 “电梯停止当前状态 按下 5 楼按钮事件→ 电梯上行目标状态”。动作Action在状态转移过程中或进入 / 退出某个状态时执行的逻辑。例如 “电梯切换到上行状态时启动电机并播报‘前往 5 楼’”、“订单变为已支付时生成物流单号并发送通知”。3. 状态机的核心价值解决什么问题在编程中状态机主要解决复杂状态切换的逻辑混乱问题具体价值体现在消除大量嵌套if/else或switch/case让状态相关逻辑更清晰、更易维护明确状态转移规则减少 “非法状态” 出现的概率例如订单已取消后无法再触发支付状态与行为解耦便于扩展新状态和新转移规则符合开闭原则逻辑可追溯性强每个状态的行为和转移都有明确定义便于调试。二、C# 中状态机的两种实现方式下面以电商订单状态流转为场景最经典的状态机应用场景之一讲解两种常用实现方式。场景定义统一约束先明确订单的核心状态、事件和转移规则核心状态State触发事件Event目标状态执行动作Action待支付Pending用户支付成功已支付Paid生成物流单号、发送支付成功通知待支付Pending用户取消订单已取消Cancelled释放库存、发送取消通知已支付Paid商家发货已发货Shipped更新物流信息、发送发货通知已发货Shipped用户确认收货已完成Completed完成订单结算、关闭交易前置准备定义枚举状态和事件首先用 C# 枚举明确订单的状态和触发事件提高代码可读性和类型安全性using System; using System.Collections.Generic; // 订单状态枚举 public enum OrderState { Pending, // 待支付 Paid, // 已支付 Shipped, // 已发货 Completed, // 已完成 Cancelled // 已取消 } // 订单事件枚举触发状态转移的信号 public enum OrderEvent { PaySuccess, // 支付成功 CancelOrder, // 取消订单 ShipGoods, // 商家发货 ConfirmReceipt // 用户确认收货 }方式 1简单状态机基于Dictionary 委托适合简单场景这种方式无需复杂的类结构通过字典存储 “当前状态 事件→转移规则”配合委托封装动作实现轻量级状态机。/// summary /// 简单订单状态机基于Dictionary委托 /// /summary public class SimpleOrderStateMachine { // 当前订单状态 public OrderState CurrentState { get; private set; } // 订单编号附加信息 public string OrderId { get; } // 定义转移规则的委托参数事件返回值是否转移成功 private delegate bool StateTransitionDelegate(OrderEvent event); // 存储所有状态的转移逻辑Key当前状态Value该状态对应的转移委托 private readonly DictionaryOrderState, StateTransitionDelegate _stateTransitions; /// summary /// 构造函数初始化订单状态机 /// /summary /// param nameorderId订单编号/param public SimpleOrderStateMachine(string orderId) { OrderId orderId; CurrentState OrderState.Pending; // 初始状态为待支付 // 初始化状态转移规则 _stateTransitions new DictionaryOrderState, StateTransitionDelegate() { { OrderState.Pending, HandlePendingState }, { OrderState.Paid, HandlePaidState }, { OrderState.Shipped, HandleShippedState }, { OrderState.Completed, HandleCompletedState }, { OrderState.Cancelled, HandleCancelledState } }; } /// summary /// 触发事件驱动状态机转移 /// /summary /// param nameevent触发事件/param /// returns转移是否成功/returns public bool TriggerEvent(OrderEvent event) { if (_stateTransitions.TryGetValue(CurrentState, out var transitionDelegate)) { return transitionDelegate(event); } Console.WriteLine($【订单{OrderId}】未知状态{CurrentState}无法处理事件{event}); return false; } #region 各状态的转移逻辑处理核心状态事件→转移动作 /// summary /// 处理“待支付”状态的转移逻辑 /// /summary private bool HandlePendingState(OrderEvent event) { switch (event) { case OrderEvent.PaySuccess: // 执行状态转移前/后的动作 Console.WriteLine($【订单{OrderId}】开始处理支付成功逻辑...); GenerateLogisticsNo(); // 生成物流单号 SendNotification(支付成功订单已确认); // 发送通知 // 更新当前状态 CurrentState OrderState.Paid; Console.WriteLine($【订单{OrderId}】状态已从{OrderState.Pending}→{OrderState.Paid}); return true; case OrderEvent.CancelOrder: Console.WriteLine($【订单{OrderId}】开始处理取消订单逻辑...); ReleaseStock(); // 释放库存 SendNotification(订单已取消库存已释放); CurrentState OrderState.Cancelled; Console.WriteLine($【订单{OrderId}】状态已从{OrderState.Pending}→{OrderState.Cancelled}); return true; default: Console.WriteLine($【订单{OrderId}】待支付状态无法处理事件{event}); return false; } } /// summary /// 处理“已支付”状态的转移逻辑 /// /summary private bool HandlePaidState(OrderEvent event) { if (event OrderEvent.ShipGoods) { Console.WriteLine($【订单{OrderId}】开始处理商家发货逻辑...); UpdateLogisticsInfo(顺丰速运SF1234567890); SendNotification(商家已发货请注意查收); CurrentState OrderState.Shipped; Console.WriteLine($【订单{OrderId}】状态已从{OrderState.Paid}→{OrderState.Shipped}); return true; } Console.WriteLine($【订单{OrderId}】已支付状态无法处理事件{event}); return false; } /// summary /// 处理“已发货”状态的转移逻辑 /// /summary private bool HandleShippedState(OrderEvent event) { if (event OrderEvent.ConfirmReceipt) { Console.WriteLine($【订单{OrderId}】开始处理确认收货逻辑...); CompleteOrderSettlement(); SendNotification(订单已完成感谢您的购买); CurrentState OrderState.Completed; Console.WriteLine($【订单{OrderId}】状态已从{OrderState.Shipped}→{OrderState.Completed}); return true; } Console.WriteLine($【订单{OrderId}】已发货状态无法处理事件{event}); return false; } /// summary /// 处理“已完成”状态的转移逻辑终态无后续转移 /// /summary private bool HandleCompletedState(OrderEvent event) { Console.WriteLine($【订单{OrderId}】订单已完成无法处理任何事件{event}); return false; } /// summary /// 处理“已取消”状态的转移逻辑终态无后续转移 /// /summary private bool HandleCancelledState(OrderEvent event) { Console.WriteLine($【订单{OrderId}】订单已取消无法处理任何事件{event}); return false; } #endregion #region 订单相关动作业务逻辑 private void GenerateLogisticsNo() { Console.WriteLine($【订单{OrderId}】生成物流单号LOG{Guid.NewGuid():N.Substring(0, 10)}); } private void SendNotification(string message) { Console.WriteLine($【订单{OrderId}】发送通知{message}); } private void ReleaseStock() { Console.WriteLine($【订单{OrderId}】释放商品库存成功); } private void UpdateLogisticsInfo(string logisticsInfo) { Console.WriteLine($【订单{OrderId}】更新物流信息{logisticsInfo}); } private void CompleteOrderSettlement() { Console.WriteLine($【订单{OrderId}】完成订单结算交易关闭); } #endregion }测试代码使用状态机class Program { static void Main(string[] args) { // 1. 创建简单订单状态机实例 var orderStateMachine new SimpleOrderStateMachine(ORDER_20260112_001); // 2. 按业务流程触发事件驱动状态转移 Console.WriteLine( 第一步用户支付订单 ); orderStateMachine.TriggerEvent(OrderEvent.PaySuccess); Console.WriteLine(\n 第二步商家发货 ); orderStateMachine.TriggerEvent(OrderEvent.ShipGoods); Console.WriteLine(\n 第三步用户确认收货 ); orderStateMachine.TriggerEvent(OrderEvent.ConfirmReceipt); Console.WriteLine(\n 第四步尝试在已完成状态下取消订单非法操作 ); orderStateMachine.TriggerEvent(OrderEvent.CancelOrder); Console.ReadKey(); } }运行结果 第一步用户支付订单 【订单ORDER_20260112_001】开始处理支付成功逻辑... 【订单ORDER_20260112_001】生成物流单号LOGa1b2c3d4e5 【订单ORDER_20260112_001】发送通知支付成功订单已确认 【订单ORDER_20260112_001】状态已从Pending→Paid 第二步商家发货 【订单ORDER_20260112_001】开始处理商家发货逻辑... 【订单ORDER_20260112_001】更新物流信息顺丰速运SF1234567890 【订单ORDER_20260112_001】发送通知商家已发货请注意查收 【订单ORDER_20260112_001】状态已从Paid→Shipped 第三步用户确认收货 【订单ORDER_20260112_001】开始处理确认收货逻辑... 【订单ORDER_20260112_001】完成订单结算交易关闭 【订单ORDER_20260112_001】发送通知订单已完成感谢您的购买 【订单ORDER_20260112_001】状态已从Shipped→Completed 第四步尝试在已完成状态下取消订单非法操作 【订单ORDER_20260112_001】订单已完成无法处理任何事件CancelOrder方式 2面向对象状态机基于状态模式适合复杂场景这种方式是状态模式State Pattern的典型应用将每个状态封装为独立的类状态的转移逻辑和动作都内聚在对应状态类中符合 “单一职责原则”扩展性更强新增状态只需新增一个状态类无需修改原有代码。步骤 1定义状态接口统一所有状态的行为/// summary /// 订单状态接口统一所有订单状态的行为 /// /summary public interface IOrderState { /// summary /// 处理当前状态下的事件驱动状态转移 /// /summary /// param nameorderContext订单上下文持有状态机的核心信息/param /// param nameevent触发事件/param void Handle(OrderContext orderContext, OrderEvent event); }步骤 2定义订单上下文封装状态机的公共信息和状态切换/// summary /// 订单上下文状态机的载体持有当前状态和公共信息 /// /summary public class OrderContext { // 当前订单状态面向接口编程 public IOrderState CurrentState { get; set; } // 订单编号 public string OrderId { get; } // 构造函数初始化上下文 public OrderContext(string orderId) { OrderId orderId; // 初始状态为待支付 CurrentState new PendingState(); } /// summary /// 触发事件委托给当前状态处理 /// /summary /// param nameevent触发事件/param public void TriggerEvent(OrderEvent event) { CurrentState.Handle(this, event); } #region 订单公共动作供各状态类调用 public void GenerateLogisticsNo() { Console.WriteLine($【订单{OrderId}】生成物流单号LOG{Guid.NewGuid():N.Substring(0, 10)}); } public void SendNotification(string message) { Console.WriteLine($【订单{OrderId}】发送通知{message}); } public void ReleaseStock() { Console.WriteLine($【订单{OrderId}】释放商品库存成功); } public void UpdateLogisticsInfo(string logisticsInfo) { Console.WriteLine($【订单{OrderId}】更新物流信息{logisticsInfo}); } public void CompleteOrderSettlement() { Console.WriteLine($【订单{OrderId}】完成订单结算交易关闭); } #endregion }步骤 3实现各个具体状态类内聚对应状态的逻辑#region 具体状态类 /// summary /// 待支付状态 /// /summary public class PendingState : IOrderState { public void Handle(OrderContext orderContext, OrderEvent event) { switch (event) { case OrderEvent.PaySuccess: Console.WriteLine($【订单{orderContext.OrderId}】开始处理支付成功逻辑...); orderContext.GenerateLogisticsNo(); orderContext.SendNotification(支付成功订单已确认); // 切换到已支付状态 orderContext.CurrentState new PaidState(); Console.WriteLine($【订单{orderContext.OrderId}】状态已从待支付→已支付); break; case OrderEvent.CancelOrder: Console.WriteLine($【订单{orderContext.OrderId}】开始处理取消订单逻辑...); orderContext.ReleaseStock(); orderContext.SendNotification(订单已取消库存已释放); // 切换到已取消状态 orderContext.CurrentState new CancelledState(); Console.WriteLine($【订单{orderContext.OrderId}】状态已从待支付→已取消); break; default: Console.WriteLine($【订单{orderContext.OrderId}】待支付状态无法处理事件{event}); break; } } } /// summary /// 已支付状态 /// /summary public class PaidState : IOrderState { public void Handle(OrderContext orderContext, OrderEvent event) { if (event OrderEvent.ShipGoods) { Console.WriteLine($【订单{orderContext.OrderId}】开始处理商家发货逻辑...); orderContext.UpdateLogisticsInfo(顺丰速运SF1234567890); orderContext.SendNotification(商家已发货请注意查收); orderContext.CurrentState new ShippedState(); Console.WriteLine($【订单{orderContext.OrderId}】状态已从已支付→已发货); return; } Console.WriteLine($【订单{orderContext.OrderId}】已支付状态无法处理事件{event}); } } /// summary /// 已发货状态 /// /summary public class ShippedState : IOrderState { public void Handle(OrderContext orderContext, OrderEvent event) { if (event OrderEvent.ConfirmReceipt) { Console.WriteLine($【订单{orderContext.OrderId}】开始处理确认收货逻辑...); orderContext.CompleteOrderSettlement(); orderContext.SendNotification(订单已完成感谢您的购买); orderContext.CurrentState new CompletedState(); Console.WriteLine($【订单{orderContext.OrderId}】状态已从已发货→已完成); return; } Console.WriteLine($【订单{orderContext.OrderId}】已发货状态无法处理事件{event}); } } /// summary /// 已完成状态终态 /// /summary public class CompletedState : IOrderState { public void Handle(OrderContext orderContext, OrderEvent event) { Console.WriteLine($【订单{orderContext.OrderId}】订单已完成无法处理任何事件{event}); } } /// summary /// 已取消状态终态 /// /summary public class CancelledState : IOrderState { public void Handle(OrderContext orderContext, OrderEvent event) { Console.WriteLine($【订单{orderContext.OrderId}】订单已取消无法处理任何事件{event}); } } #endregion步骤 4测试面向对象状态机class Program { static void Main(string[] args) { // 1. 创建订单上下文状态机载体 var orderContext new OrderContext(ORDER_20260112_002); // 2. 触发事件驱动状态转移 Console.WriteLine( 第一步用户支付订单 ); orderContext.TriggerEvent(OrderEvent.PaySuccess); Console.WriteLine(\n 第二步商家发货 ); orderContext.TriggerEvent(OrderEvent.ShipGoods); Console.WriteLine(\n 第三步用户确认收货 ); orderContext.TriggerEvent(OrderEvent.ConfirmReceipt); Console.WriteLine(\n 第四步尝试在已完成状态下取消订单非法操作 ); orderContext.TriggerEvent(OrderEvent.CancelOrder); Console.ReadKey(); } }运行结果与简单状态机一致扩展性更强 第一步用户支付订单 【订单ORDER_20260112_002】开始处理支付成功逻辑... 【订单ORDER_20260112_002】生成物流单号LOGf6g7h8i9j0 【订单ORDER_20260112_002】发送通知支付成功订单已确认 【订单ORDER_20260112_002】状态已从待支付→已支付 第二步商家发货 【订单ORDER_20260112_002】开始处理商家发货逻辑... 【订单ORDER_20260112_002】更新物流信息顺丰速运SF1234567890 【订单ORDER_20260112_002】发送通知商家已发货请注意查收 【订单ORDER_20260112_002】状态已从已支付→已发货 第三步用户确认收货 【订单ORDER_20260112_002】开始处理确认收货逻辑... 【订单ORDER_20260112_002】完成订单结算交易关闭 【订单ORDER_20260112_002】发送通知订单已完成感谢您的购买 【订单ORDER_20260112_002】状态已从已发货→已完成 第四步尝试在已完成状态下取消订单非法操作 【订单ORDER_20260112_002】订单已完成无法处理任何事件CancelOrder三、两种实现方式的对比与适用场景实现方式优点缺点适用场景简单状态机Dictionary 委托实现简单、轻量级、无需额外类结构、开发效率高扩展性差新增状态需修改字典配置和转移逻辑、复杂场景下逻辑易混乱状态数量少5 个以内、转移规则简单、无需频繁扩展的场景面向对象状态机状态模式扩展性强新增状态只需新增类、逻辑内聚、可读性高、符合开闭原则实现复杂、类数量多、有一定学习成本状态数量多、转移规则复杂、需要频繁扩展新增状态 / 事件的企业级场景如电商、物流、工作流四、C# 中的高级状态机对于超复杂的状态机场景如带状态历史、并发状态、子状态机无需重复造轮子可以使用成熟的第三方库Stateless轻量级、开源的.NET 状态机库支持流畅 API、委托、异步动作、状态持久化等NuGet 安装Install-Package StatelessAutomatonymous基于 MassTransit 的事件驱动状态机库支持复杂的异步流转和分布式场景NuGet 安装Install-Package Automatonymous总结状态机是描述对象有限状态、转移规则、事件和动作的模型核心价值是解决复杂状态切换的逻辑混乱状态机的 4 个核心要素状态State、事件Event、转移Transition、动作ActionC# 中简单场景可使用Dictionary委托实现轻量级状态机复杂场景推荐基于状态模式的面向对象实现状态机的核心思想是 “状态驱动行为”通过明确的转移规则减少非法状态提高代码的可维护性和扩展性。