这个系列最终实现的状态机并不是一个标准的状态机,把状态机的很多标准的概念进行了简化,对概念的东西做了减法,实现了具备基本功能的状态机(很多所谓状态机更高级的功能,如:伪态,也可以在基本功能实现)。整个状态机的实现将分为下面几个章节介绍
- 状态机介绍
- 简单有限状态机的实现
- 简单有限状态机的应用实例
- 简单状态机功能增强
- 有限状态机状态持久化设计
- 有限状态机持久化实现
当前章节以理论为主
有限状态机概念
有限状态机简称就是状态机,因为一般的状态机的状态都是离散和可举的,即为有限,所以后面的介绍都不加有限二字。状态机表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。通俗的描述状态机就是定义了一套状态変更的流程:状态机包含一个状态集合,定义当状态机处于某一个状态的时候它所能接收的事件以及可执行的行为,执行完成后,状态机所处的状态。所以状态机会包含以下几个重要的元素:
- State:状态。一个标准的状态机最少包含两个状态:初始和终态。初态是状态机初始化后所处的状态,而终态顾名思义就是状态机结束时所处的状态。其他的状态都是一些流转中停留的状态。标准的状态机还会涉及到一些中间态,存在中间态的状态机流程就会比较复杂(用处也不是特别大,而且可以通过其他方式实现),所以在目标实现的状态机里不会引入这个概念。
- Event:事件。还有中描述叫Trigger,表达的意思都一样,就是要执行某个操作的触发器或口令:当状态机处于某个状态时,只有外界告诉状态机要干什么事情的时候,状态机才会去执行具体的行为,来完成外界想要它完成的操作。比如出去吃饭,说“点菜”,服务员才会拿着小本过来记录你要吃的菜,说的那句“点菜”,就相当于Event。
- Action:行为。状态变更索要执行的具体行为。还是拿上面点菜的例子,服务员拿小本记录你定的菜的过程就是Action
- Transition:变更。一个状态接收一个事件执行了某些行为到达了另外一个状态的过程就是一个Transition。定义Transition就是在定义状态机的运转流程。
上图就是一个最简单的状态机,一个初态,一个流转状态,一个终态,初态到流状态是不需要任何操作的,State1当发生了Event1事件时,执行Action1到达了终态。(我们最终实现的状态机,会把初态和终态都当做一个流状态来对待)。
说了这么多,状态机能干什么?状态机主要的应用场景就是流程控制。一个状态机定义以后,在某个状态下就只接收固定的Event,也就是执行指定的操作,这样流程就能按照预期定义的那样流转,不会出现乱入的情况,执行了一些在某状态下不允许执行的操作。一个很典型的应用就是工作流引擎:以工作流中典型的审批流程为例,审批流程按照预先定义的流程流转的固定的某些人手里,只有这一批固定的人才能审批,当审批后(可能是一个人审批,也可能是多个人审批)才会流转到下个节点,由下个节点的审批人继续审批,一直流转到最后一个节点。状态机的流转可以人工干预,也可以自动流转。定义为自动流转后,把业务流程定义完成后,只要添加一个定时任务,整个流程的运转就都由状态机来完成了。此外,当状态机加入了持久化操作后,所有的状态流转都会落地,当业务出现异常,方便定位问题,当流程定义的足够细粒度的话,还可以通过驱动状态机来实现重入,恢复异常的节点。
状态模式
在实现状态机之前,我们顺便简单的看一下设计模式中的状态模式,这个模式跟我们实现状态机的代码结构还是有一定的关系的。
状态模式:封装基于状态的行为,并将行为委托到当前的状态。
试想一下,现在有一种业务场景存在多个状态,比如一个要遭受攻击的游戏人物,当人物遭受攻击后我们要减少人物的血量,而当前人物可能处于的状态有如下(游戏中常见的一些场景):刚复活(对一切攻击免疫),正常状态,物理攻击免疫,魔法攻击免疫,攻击随机无效,各种叠加态。当攻击来了,人物该怎么掉血。在非使用状态模式的情况下,一种常见的写法,人物接受攻击,然后开始各种判断现在人物所处于的状态,各种if...else,当新的需求来额时候,就修改这些if...else。而采用状态模式,行为委托类保存着当前人物所处的状态,当攻击来了,委托类会把该攻击交由持有的状态来处理,实现了对修改关闭,对扩展开放。类图如下(具体就不上代码了,感兴趣的可以自己研究一下):
状态模式- Context:可以理解为上下文,它持有当前的状态,同时对外暴露状态行为接口
- State:定义了状态下的行为接口
- ConcreteState:行为接口的具体实现
其中Context是一个关键,在我们将要实现的状态机里扮演者重要的角色。
此外我们将要的实现的状态机远远不是一个状态模式的一个实现,要比它复杂的多。
目标状态机功能介绍
- 状态机的定义:通过定义State,Event,Action,Transition来实现状态机的流转,摒弃标准状态机中那些较复杂的概念(通过其他方式来实现所谓的较复杂的操作)
- 状态持久化:数据持久化到数据库,实现状态机的中断重启
- 上下文保存与传递:提供一套流程流转过程中参数的传递机制
- 并发控制:提供不同状态机隔离,同一状态机单实例运行机制
- 功能增强:接口或注解的形式实现自触发,重试,定时执行
github上有一开源状态机,算是github上状态机系列java得星最多的项目,功能已经做的很强大,本人早期的时候关注过,但是到目前为止已经做的很复杂了,超出了大部分常规的使用场景,而且几个版本下来,代码风格也有了很大的变化。感兴趣的同学可以先看一下:
https://github.com/hekailiang/squirrel
此外Spring也有一套状态机,但对spring版本有要求,有生产需求的同学也可以考虑一下
网友评论