状态机
在理解状态机之前,总是把状态里简单地理解为状态模式,最近,我仔细分析了状态机的实现机制,发现状态机和状态模式还是有很大的不同。
一,状态模式是具体的,针对每个需求有一个状态集,并为其实现特有的迁移机制。状态机是抽象的,不是针对特定的需求,而是对各种与相关的问题的进一步抽象,那么用状态机回头去实现状态模式的时候,只需要关注问题本身,而不用去关心如何实现,也就是说你只需要绘制出状态迁移图,状态机就能帮你去实现。
二,状态模式的是命令式的,我们必须一步一步地去实现状态之间如何迁移,以及迁移过程中需要做一些额外的事情。状态机是声明式的,使用状态机,你只需要声明状态及状态的迁移路线,而不需要去提供执行层面的命令,状态机自动帮你去做。
三,状态模式容易理解,状态机确实不是那么容易理解,估计很多人会想我一样,认为其没有什么差别,这是不对的。(这也算是一个区别,哈哈)
区分了这么多,言归正传,来分析一下一个典型的状态机的实现,首先简要看一下类图:
一,Event,顾名思义是事件的意思,在状态迁移过程中所发生的事情,分为主动事件ActiveEvent(对应原著里的Command),被动事件PassiveEvent。
主动事件是进入某个状态以后自动往状态机以外发送信息的事件,被动事件是被状态机接受处理完成状态迁移的事件。
二,CommandChannel,命令通道用来接收被动事件和发送主动事件,被控制器所持有,特定的需求可以实现各自具体的命令通道。
三,State,状态和状态模式里的每个具体状态对应,区别是状态模式里的每个状态对应一个特定的状态类(命令式,有效的信息有类名,迁移方法),而这里的State是一个简单的结构,主要包括名称,迁移表(对应前者的类名和迁移方法),主动事件表(进入该状态以后自动调用),自动激发事件表,在主动事件调用完毕以后,主动向状态机本身发送被动事件,用途是有的状态只是一个中间临时状态,会被自动迁移到下一个状态,比如一扇门而言:Open事件导致门进入Opening(正在打开)状态,这个状态会做一个动作(角度慢慢扩大),然后自动迁移到Opened(已经打开)状态,那么Opening就会拥有一个Open的自动激发事件,在其处理的结尾将这个事件发送到状态机以自动切换到Opened状态。
三,Transition,状态切换路径,包含EventCode(事件源,指定了当前状态下对该事件感兴趣),Source(源状态),Trigger(触发器),Target(目的状态)。
四,StateMachine,到状态机了,状态机本身很简单,包含Start(状态机的起始状态),AllStates(该状态机的所有可能的状态)。
五,Controller,控制器负责接收外部事件Handle(eventcode),指导状态机完成窗台迁移,包括CurrentState(状态机内部的当前状态),Machine(状态机),CommandChannel(命令通道)。
以上介绍了简单的类图,值得提醒的一点就是,从静态结构看,唯一可以扩展的地点就是CommandChannel,这个类有一个DoSend方法需要实现,每个具体的应用实现这个方法来根据其状态参数做具体的操作。
下面从源代码的角度来观察:
一,抽象事件
二,主动事件
三,被动事件
四, 状态
五,状态机
六,迁移
七,控制器
以上是详细的代码,有兴趣看完的话,我也是醉了(同道中人啊)。下面我做两个简单的例子介绍,都是关于门的例子第一个例子如下:有两个状态:开和关,在开的状态下接受到Close事件,则迁移到关状态,在关状态下,接受到Open事件,则迁移到开状态。测试如下:
代码是不是"声明式"味道的啊:)。
第二个例子在这个例子上增加两个状态:正在关闭,正在打开,如下:
测试代码如下:
参考书目《领域特定语言》