`

转载:从工作流状态机实践中总结状态模式使用心得

阅读更多
出处已不清楚,属于转载文章



  状态模式好像是很简单的模式,正因为状态好像是个简单的对象,想复杂化实现设计模式就不是容易,误用情况很多。

  我个人曾经设计过一个大型游戏系统的游戏状态机,游戏状态可以说是游戏设计的主要架构,但是由于系统过分复杂

  和时间仓促,并没有真正实现状态模式。

  目前在实现一个电子政务项目中,需要进行流程状态变化,在电子政务设计中,我发现,如果一开始完全按照工作流

  规范开发,难度很大,它和具体项目实践结合无法把握,而且工作流规范现在有wfmc,还有bpml,选择也比较难。因

  此,我决定走自创的中间道路。

  因为,我需要做一个状态机API,或者说状态机框架,供具体系统调用:类如公文流转应用或信息发报送应用等。

  好的状态模式必须做到两点:

  1. 状态变化必须从外界其它逻辑划分出来。

  2. 状态必须可方便拓展,对其它代码影响非常小。

  要做到这两点,必须先明确状态变化机制,状态变化实际是由Event事件驱动的,可以认为是Event-condition-State,

  在MVC模式一般是Event-condition-Action实现。状态模式需要封装的是Event-condition-State中的condition-State

  部分。

  清晰理解状态和流程的关系也非常重要,因为状态不是孤立的,可以说和流程是点和线的关系,状态从一个方面说明

  了流程,流程是随时间而改变,状态是截取流程某个时间片。因此,必须明白使用状态模式实现状态机实际是为了更

  好地表达和说明流程。

  状态和流程以及事件的关系如下:

  |Event___currentState__|______newState___

  图中表示了是事件改变了流程的状态,在业务逻辑中,经常发生的是事件,如果不使用状态模式,需要在很多业务逻



  辑处实现事件到状态判定和转换,这有很多危险性。

  最大的危险是系统没有一个一抓就灵的主体结构,以那个游戏系统为例,在没有状态模式对状态提炼的情况下,状态

  改变由每个程序员想当然实现,导致每个程序员开发的功能在整合时就无法调试,因为这个程序员可能不知道那个程

  序员的代码在什么运行条件下改变了游戏状态,结果导致自己的代码无法运行。

  这种现象实际上拒绝了项目管理的协作性,大大地拖延项目进度(程序员之间要反复商量讨论对方代码设计)。从这

  一点也说明,一个好的架构设计是一个项目快速成功完成的基础技术保证,没有这个技术基础,再先进的项目管理手

  段也是没有效率的,或者是笨拙的。

  状态模式对于很多系统来说,确实是架构组成一个重要部分。

  下面继续讨论如何实现一个好的状态模式,为了实现好的状态模式,必须在状态模式中封装下面两个部分:

  1. 状态转换规则(行为)

  2. 状态属性(属性)

  状态转换行为有两种划分标准:

  1. run和next两个行为,run是当前状态运行行为,next是指在Event参与下,几种可能转向的下一个状态。

  2. stateEnter和stateExit, 状态进入和状态退出。

  如果用进入一个个房间来表示状态流程的话, 第一种分析是只重视着“在房间里”和“如何转入下一个房间”,这两种行

  为一旦确定,可以被反复使用,进而一个流程的状态切换可以全部表达出来。

  第二中分析方法有所区别,只重视进入房间和离开房间这个两个行为,同样,这种模型也可以被反复利用在其它房间,

  一个流程的状态切换也可以全部表达出来。

  具体选择取决于你的需求,比如,如果你在进入一个状态开始,要做很多初始化工作,那么第二种模型就很适合。



  状态变化都离不开一个主体对象,主体对象可以说包含状态变化(行为)和状态属性(属性),假设为StateOwner,

  StateOwner有两个部分组成:Task/事情和状态。任何一个Task/事情都会对应一个状态。

  这样,我们已经抽象出两个主要对象:状态State和StateOwner。

  为了封装状态变化细节,我们可以抽象出一个状态机StateMachine来专门实现状态根据事情实现转换。

  这样,客户端外界通过状态机可访问状态模式这个匣子。在实践中,外界客户端需要和状态机实现数据交换,我们把

  它也分为两种:属性和行为。

  其中属性可能需要外界告诉状态状态变化的主体对象Task,解决状态的主人问题,是谁的问题;行为可能是需要持久

  化当前这个主体对象的状态到数据库。

  这两种数据交换可以分别通过StateOwner和StateMachine与整个状态机实现数据交换,这样,具体状态和状态切换也

  和外界实现了解耦隔离。

  因此好的状态模式实现必须有下列步骤:

  (1)将每个状态变成State的子类,实现每个状态对象化。

  (2)在每个状态中,封装着进入下一个状态可能规则,这些规则是状态变化的核心,换句话说,统一了状态转换的规则。

  具体可采取run和next这样的转换行为。

  下面是一个子状态代码:

public class Running extends StateT{
 //
 public void run(StateOwner stateOwner){
   stateOwner.setCurrentState(this);
 }
 //转换到下一个状态的规则
 //当前是Running状态,下一个状态可能是暂停、结束或者强制退出等
 //状态,但是绝对不会是Not_Started这样的状态
 //转换规则在这里得到了体现。
 public State next(Event e) {
  if(transitions == null){
    addEventState(new EventImp("PAUSE"), new Suspended());
    addEventState(new EventImp("END"), new Completed());
    addEventState(new EventImp("STOP"), new Aborted());
  }
  return super.next(e);
 }
}  
外界直接调用 StateMachine的关键方法transition;实行状态的自动转变。 
public class StateMachine {
/**
  * 状态切换
  * 根据Event参数,运行相应的状态。
  * 1. 获得当前状态
  * 2. 使用当前状态的next()转换
  *         |Event
  * ___currentState__|______newState___
  *
  * @param inputs
  */
 public final void transition(String taskid, Event e) throws Exception {
  State currentState = readCurrentState(taskid); //从数据库获得当前状态
  StateOwner stateOwner = new StateOwner(taskid, currentState);
  //转换状态
  currentState = currentState.next(e);
  if (currentState != null) {
   currentState.run(stateOwner);
   saveCurrentState(stateOwner); //保存当前状态
  }
 }
}
分享到:
评论

相关推荐

    十分详细的工作流实例

    同时,你会看到如何使用工作流服务(Workflow Services)进行服务间通信,以及状态机和顺序工作流的设计模式。此外,还要注意事务处理、异常管理和持久化机制,这些都是确保工作流系统稳定性和可靠性的重要组成部分...

    二十三种设计模式【PDF版】

    为能和大家能共同探讨"设计模式",我将自己在学习中的心得写下来,只是想帮助更多人更容易理解 GoF 的《设计模式》。由 于原著都是以C++为例, 以Java为例的设计模式基本又都以图形应用为例,而我们更关心Java在中间件等...

    Gef 学习总结

    - **流程图设计**:流程图、工作流图、状态机等都可以用Gef实现。 - **网络拓扑图**:绘制和编辑网络设备的布局和连接。 - **电路图设计**:模拟电路设计和分析工具。 - **系统配置工具**:图形化展示和编辑系统...

    Openflow学习总结.pdf

    通过OpenFlow,控制平面被从交换机中分离出来,由一个或多个集中的控制器负责决策如何处理数据包。 随着OpenFlow技术的发展,高性能的OpenFlow交换机应运而生,这些交换机能够在多千兆的速度下工作。然而,即使是...

    电工实习实验报告 制作收音机 报警器 电梯装置

    ### 电工实习实验报告知识点总结 ...通过对收音机、报警器、三相电机控制和家庭电器电路设计等项目的实践,学生们深刻理解了电气元件的工作原理和应用场景,同时也锻炼了团队合作精神和创新思维能力。

    实验1、CC2530 流水灯实验_cc2530_

    3. **循环控制**:通过一个计数器或者状态机来控制LED的亮灭顺序。每次循环,计数器递增,根据计数器的值来决定哪个LED应该被点亮。 4. **延时处理**:为了观察到明显的流水效果,需要在每次切换LED状态后加入一定...

    药片装瓶系统设计, 数字逻辑课程 verilog 实践

    ### 药片装瓶系统设计相关知识点 #### 一、背景介绍 在数字逻辑课程设计项目中,学生们被要求运用...通过这样的项目实践,学生可以在实践中加深对数字逻辑设计的理解,同时提升自己的编程技能和解决问题的能力。

    头歌教学实践平台 计算机组成原理 数字逻辑-交通灯系统设计(HUST);以及存储系统设计;运算器设计;MIPS CPU设计

    - 状态机的设计应考虑到状态转移逻辑,包括增加、减少操作以及进位/借位处理。 - 可以通过状态转移表来清晰地定义每个状态下的行为。 - **1.7双向BCD计数器输出函数设计** - 输出函数负责根据当前状态输出相应的...

    序列检测器实验报告

    - **工作原理**:基于状态机的工作机制,通过监测输入信号的变化,识别目标序列,并输出相应的结果。 #### 设计实现 - **主程序设计**: - **模块定义**:定义了一个名为`modulet`的模块,包含输入端口`clk`...

    JBPM4.3 学习笔记

    文件"JBPM4学习笔记.doc"可能包含了博主在学习过程中整理的详细笔记,涵盖了上述所有知识点的实践经验和心得,对于理解JBPM4.3的使用和开发有着重要的参考价值。 总结,JBPM4.3的学习笔记涵盖了流程建模、执行、...

    EA UML活动图第2次笔记.docx

    活动状态是活动图中的基本概念,它用于表达状态机中的非原子的运行。活动状态可以分解成其他子活动或者动作状态。活动状态的内部活动可以用另一个活动图来表示。活动状态可以有入口动作和出口动作,也可以有内部转移...

    FPGA:除法器设计.doc

    课程设计心得体会部分,学生应总结在设计过程中学习到的知识点,遇到的挑战,以及解决问题的经验,同时反思设计的优缺点,提出可能的改进方向。 参考文献应列出在设计过程中参考的相关书籍、论文和技术文档,以体现...

    Linux 命令手册

    - `cut`:从文件中切割出指定部分的数据。 - `sort`:对文件内容进行排序。 7. **脚本编写**: - `bash`:常用的shell类型,用于编写脚本。 - `sh`:另一种常见的shell类型。 - `crontab`:用于计划周期性执行...

    shiyan6.docx

    2. **状态图**:状态图用于表示有限状态机(FSM)的工作流程,它是描述序列逻辑行为的重要工具。通过状态转移图,学生可以清晰地理解控制逻辑的运行过程。 3. **流程图**:流程图展示了算法的步骤和决策流程,有助...

    计算机组成与体系结构实验报告 基本模型机设计

    - 首先断开所有实验连线,根据实验手册中的指引,将系统工作模式设置为“微控/在线”。 2. **程序写入**: - 在待命状态下,通过键盘输入数字“1”,选择基本模型机代号。 - 接着输入“减址”命令,实验装置将...

    基于labview的交通灯设计

    3.3 时间信号的分段涉及到逻辑控制,可能需要用到LabVIEW的case结构或状态机设计模式。 3.4 各阶段程序的编写需要考虑交通灯状态之间的平滑过渡,确保交通流的顺畅。 通过这样的设计,不仅可以满足课程设计的技术...

    计算机组成原理课设

    - 包括时钟信号的产生与分发,以及状态机的设计等。 #### 三、二进制微代码表设计 微代码表是微程序的编码表示形式,用于控制模型机内部各部件之间的数据流和控制信号。设计时需考虑: - **微指令的格式:**确定...

    《电子商务概论》实验大纲.pdf

    《电子商务概论》实验大纲是针对电子商务及相关专业学生设计的一门实践性教学课程,旨在通过实验环节强化理论学习...实验教学旨在使学生能够在实践中巩固理论知识,提升电子商务实践操作技能,以应对实际工作中的挑战。

    编译原理报告 有程序截图心得

    它基于一种叫做状态机的模型,每个状态代表文法的一部分,而转移则由输入符号驱动。LR(0)分析器会构建一个解析表,其中包含了对于每个状态和输入符号的处理规则。当输入源代码与解析表匹配时,表示语法是正确的,...

Global site tag (gtag.js) - Google Analytics