【技术】state-machine状态机设计模式在项目中的应用

  • 时间:
  • 浏览:2251
  • 来源:吧啦熊

状态机的定义

状态机是一种用来进行对象建模的工具,它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止。

状态模式主要用来解决对象状态转换比较复杂的情况。它把状态的逻辑判断转移到不同的类中,可以把复杂的逻辑简单化。

状态机有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);

猜你喜欢

【技术】state-machine状态机设计模式在项目中的应用

状态机的定义状态机是一种用来进行对象建模的工具,它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前”节点的转移函数

2020-05-21

CentOS 7.x下使用yum安装MySQL5.6

CentOS 7.x下使用yum安装MySQL5.6

2020-04-16

不破不立,继续前行

2019,不破不立,继续前行。

2018-12-24

【大结局】人不彪悍枉少年:青春略有遗憾才更值得回味

网剧《人不彪悍枉少年》迎来了大结局。和小编预想的不同,无论是杨夕、花彪还是黄澄澄和李渔,没有一对最终在一起。花彪因奶奶患上老年痴呆,选择在奶奶彻底记忆不清前带奶奶环游世界。杨夕

2018-12-21

清华学霸情侣马艺妮和宋思睿,被爆学术造假,死缠烂打约3p

清华大学的特将候选人,还参加过最强大脑的清华校花马艺妮和男友宋思睿,两人死缠烂打约北京大学妹子3p被曝光。马艺妮曾在《最强大脑》节目中,说自己遇到了现实版的“肖奈”。不久前,北

2018-12-05