【技术】state-machine状态机设计模式在项目中的应用
- 时间:
- 浏览:2635
- 来源:吧啦熊
状态机的定义
状态机是一种用来进行对象建模的工具,它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止。
状态模式主要用来解决对象状态转换比较复杂的情况。它把状态的逻辑判断转移到不同的类中,可以把复杂的逻辑简单化。
状态机有4个要素,即现态、条件、动作、次态。其中,现态和条件是“因”, 动作和次态是“果”。
现态 - 是指当前对象的状态
条件 - 当一个条件满足时,当前对象会触发一个动作
动作 - 条件满足之后,执行的动作
次态 - 条件满足之后,当前对象的新状态。次态是相对现态而言的,次态一旦触发,就变成了现态
项目应用需求
将大的业务拆解成N个子任务类,便于业务理解和开发维护
子任务类继承同一个基类,在重载方法中实现具体业务,包括主业务逻辑、异常处理等
子任务可独立运行,也可多个子任务组合成一条任务链,支持闭环任务链
基类状态机设计
/// /// 状态
/// public enum State
{
/// /// 预备
/// Ready,
/// /// 初始化中
/// Initializing,
/// /// 运行中
/// Running,
/// /// 子进程
/// Subprocess,
/// /// 中断
/// Interrupting,
/// /// 已完成
/// Complete,
/// /// 结束
/// End,
/// /// 已退出,并释放资源
/// Exit
}
/// /// 触发器
/// public enum Trigger
{
/// /// 启动任务
/// toStart,
/// /// 执行业务逻辑
/// toRun,
/// /// 执行下条任务
/// toNext,
/// /// 中断模式
/// toInterrupt,
/// /// 完成任务
/// toComplete,
/// /// 忽略错误
/// toIgnore,
/// /// 结束任务
/// toEnd,
/// /// 退出并释放资源
/// toExit,
/// /// 循环任务
/// toLoop
}
流程设计
正常流程
执行:doCheck()->doMain()->doComplete()->[SubTask.doCheck()->...SubTask.doComplete()]->doEnd()->[SubTask.doExit()]->doExit()
解释: 通过检查前置条件 -> 执行完成主业务逻辑 -> 当前任务完成 -> 执行子任务流程 ->当前任务链完成 ->执行子任务退出 -> 执行任务退出
前置检查不通过
执行:doCheck()->doExit()
解释: 未通过检查前置条件 -> 执行任务退出
忽略主业务逻辑执行异常
执行:doCheck()->doMain()->doInterrupt()->doComplete()->[SubTask.doCheck()->...SubTask.doComplete()]->doEnd()->[SubTask.doExit()]->doExit()
解释: 通过检查前置条件 -> 执行主业务逻辑发生异常 ->异常处理,可忽略-> 当前任务完成 -> 执行子任务流程 ->当前任务链完成 ->执行子任务退出 -> 执行任务退出
不忽略主业务逻辑执行异常
执行:doCheck()->doMain()->doInterrupt()->doExit()
解释: 通过检查前置条件 -> 执行主业务逻辑发生异常 ->异常处理,无法忽略-> 执行任务退出
实现方案
引用类库
Stateless
是一款基于.NET的开源状态机库,使用它你可以很轻松的在.NET中创建状态机和以状态机为基础的轻量级工作流。
项目源代码 https://github.com/dotnet-state-machine/stateless
逻辑配置
this._machine = new StateMachine(() => _state, s => _state = s);
this._machine.Configure(State.Ready)
.OnEntry(() => this.Log("Ready", "state"))
.OnEntryFrom(Trigger.toLoop, this.Loop)
.InternalTransition(Trigger.toLoop, this.Loop)
.Permit(Trigger.toStart, State.Initializing);
this._machine.Configure(State.Initializing)
.OnEntry(() => this.Log("Initializing", "state"))
.OnEntryFrom(Trigger.toStart, this.Init)
.Permit(Trigger.toRun, State.Running)
.Permit(Trigger.toExit, State.Exit);
this._machine.Configure(State.Running)
.OnEntry(() => this.Log("Running", "state"))
.OnEntryFrom(Trigger.toRun, this.Run)
.Permit(Trigger.toExit, State.Exit)
.Permit(Trigger.toInterrupt, State.Interrupting) //任务被中断
.Permit(Trigger.toComplete, State.Complete);//任务顺利完成
this._machine.Configure(State.Interrupting)
.OnEntry(() => this.Log("Interrupting", "state"))
.OnEntryFrom(Trigger.toInterrupt, this.Interrupt)
.SubstateOf(State.Running)
// .Permit(Trigger.toExit, State.Exit)//直接退出
.Permit(Trigger.toIgnore, State.Complete);//忽略错误继续执行
this._machine.Configure(State.Complete)
.OnEntry(() => this.Log("Complete", "state"))
.OnEntry(this.Complete)
.SubstateOf(State.Running)
.Permit(Trigger.toNext, State.Subprocess)
// .Permit(Trigger.toExit, State.Exit)
.Permit(Trigger.toEnd, State.End);
this._machine.Configure(State.Subprocess)
.OnEntry(() => this.Log("Subprocess", "state"))
.OnEntryFrom(Trigger.toNext, this.Next)
.SubstateOf(State.Running)
// .Permit(Trigger.toExit, State.Exit)
.Permit(Trigger.toEnd, State.End);
this._machine.Configure(State.End)
.OnEntry(() => this.Log("End", "state"))
.OnEntryFrom(Trigger.toEnd, this.End)
.Permit(Trigger.toExit, State.Exit)
.Permit(Trigger.toLoop, State.Ready);
this._machine.Configure(State.Exit)
.OnEntry(() => this.Log("Exit", "state"))
.OnEntryFrom(Trigger.toExit, this.Exit);
猜你喜欢