状态机的一种实现jc::fsm介绍(1):状态机的模型

发表于2015-09-17
评论1 1.6k浏览
状态机的一种实现jc::fsm介绍(1):状态机的模型
陈明建(jerrychen)

为了解决玩家状态繁多,流程复杂的问题,zone上引入了状态机。jc::fsmzone上状态机的一种实现方式。

 

一、            状态的组成

在解释jc::fsm状态的组成前,先介绍一个概念,在jc::fsm中,存在从状态s进入状态s的操作,这种称为ReEnterReEnter方式的存在是为了让状态机规则表示更加简单规范。一般在需要保持状态不变情况下,执行一些操作时会使用ReEnter方式,该方式一般随后会紧跟一条code驱动规则。具体见内部返回码code驱动一节

jc::fsm状态机包含以下元素:状态(status),外部事件(event),返回码(code),处理函数集(handler)及由这些元素共同组成的转移规则(rule)

状态内部结构如下:

 

Status_name: 状态名称

Enter():当非ReEnter该状态时,调用该函数

Exit(): 当退出后非ReEnter该状态时,调用的函数

Handler1(), handler2(),……,handlerN()函数集:进入状态,并在调用enter()后,根据转移条件决定调用其中某个函数。

一个状态节点,可以没有enter()exit(),但必定至少有一个 handler()。

二、            状态转移

jc::fsm中存在两类状态转移操作:外部事件event驱动和内部返回码code驱动。

1.       外部事件event驱动

Event驱动分两种情况:ReEnter和非ReEnter方式。如下图所示:

event1驱动的状态转移是 ReEnter方式的转移。这种状态转移,enter()exit()函数都不会被调用,仅调用 handler1()函数。在实际应用中,这种转移后将会根据handler1()函数的返回码,通过返回码驱动转移到下一个状态。

event2驱动的状态转移是非ReEnter方式,这种转移会先调用status_1::exit()函数,然后调用把当前状态切换为status_2,接着执行status_2::enter()函数,最后再执行status_2::handler2()函数,然后根据handler2()返回码,进行返回码驱动。

当然由event2驱动时,也可能出现另一种情况,如下图所示中的event2

这种情况下,进入status_2后,不执行任何函数,而是停在该状态下等待外部事件进行下一步驱动。

2.       内部返回码code驱动

code驱动是为了实现函数调用后,根据执行结果进行流程选择的需求。换种方式考虑,在状态机处理函数内触发事件驱动,也可以实现这种需求,但是这种方式使用不当时容易导致状态机调用栈嵌套,从而引入bug。因此jc::fsm中,在各hanlder函数内禁止向本状态机发送事件,事件只能在状态机外部被触发,因此事件又叫做外部事件。

Code驱动理论上也包含ReEnter和非ReEnter方式,也就是说jc::fsm支持这两种方式,不过实际应用中,code驱动一般都使用非ReEnter方式。

如上图所示,经event1驱动后状态由status_1进入status_2,并执行status_2::handler3()函数。当Handler3函数返回code1时,状态由status_2转到status_3;当返回code2时,状态由status_2转到status_4,并执行status_4::handler1()函数。那如果handler3返回code3呢?code3不在图中,那么状态机将停止在status_2状态上,等待外部事件的触发。

code驱动有种情况比较特殊,这里单独提一下,大家看下图:

Jc::fsmstatus_1下,收到事件event1,以ReEnter 方式进入status_1,并执行status_1::handler1(),根据handler1返回值是否为code1决定状态机是否转移到状态status_2。由于以ReEnter方式进入status_1时,status_1::enter()status_1::exit()都不会被调用,仅调用status_1::handler1(),因此这种方式也可以理解为,status_1下接收到event1事件时,状态不转移,直接执行handler1函数。因此这种情况,在后面提到的“jc::fsm的图形化工具”中,一般以另一种更加直观的图形方式来表示:

         

从上图上可以很容易看出,status_1下收到event1事件时,执行handler1函数,如果handler1返回code1,则转移到status_2状态,否则保持在status_1状态不变。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论