有限状态机 FSM
有限状态机,(Finite State Machine,FSM),简称状态机。是一种数学抽象计算模型,描述一个对象有限数量的状态以及状态间的转移条件,触发事件等行为。其逻辑特征如下:
- 有限的状态和事件,如果无限状态,则无法描述
- 任一时刻,该对象都会处于某个确定的状态中
- 满足特定条件,状态会从一个状态转移到另一个状态
简单来讲由:状态(State)、状态转换 (State Transfer)组成一个完成的状态机FSM。FSM的下一个状态和输出是由输入和当前状态决定的。如图所示:一个由A、B、C三种状态及其状态转移组成的状态机,任一时刻,都会为A、B、C其中一种,当处于某一个状态,且又被外部事件触发时,便产生状态转换。如状态机处于状态C绿灯时,加上外部15s时间触发器,则触发C➡B状态转换条件,继而系统状态从C转移到B。
如果用代码表达,则可以表示为
char fsmstate;
switch(fsmstate){
case 'A': // 红灯状态
EntryAction(); // 进入红灯状态的动作
if (time_trigger(10)){ // 等待外部事件,如果触发则转移
fsmstate = 'C';
}
ExitAction(); // 退出红灯状态时动作
break;
case 'B': // 黄灯状态
EntryAction(); // 进入黄灯状态的动作
if (time_trigger(10)){ // 等待外部事件,如果触发则转移
fsmstate = 'C';
}
ExitAction(); // 退出黄灯状态时动作
break;
case 'C': // 绿灯状态
EntryAction(); // 进入绿灯状态的动作
if (time_trigger(10)){ // 等待外部事件,如果触发则转移
fsmstate = 'C';
}
/* 一个状态可以监听多个事件,进而实现不同的转移*/
if (Green2RedByHand()){
fsmstate = 'A';
}
ExitAction(); // 退出绿灯状态时动作
default :
return -1; // 返回故障
}
实际使用过程中,随着抽象程度的不断提高,往往会将一些与状态关联的动作绑定到状态内部,如定义状态进入动作 (EntryAction) 和退出动作(ExitAction);或将状态转换拆分为状态转换条件和一系列触发事件,实现灵活描述。
状态机编程,其实是分析一个多状态对象的有力工具,如果一个对象存在有限多个状态,且从一个状态到另一个状态有确定描述,则适合用状态机描述编程,依据当前状态及当前状态所监听的事件,产生状态转移,往往更加清晰,不易出错。
状态机的描述,也并非用图不可,用表格也是很不错的选择。如马里奥的游戏马里奥状态用表格表示
吃蘑菇 | 碰到怪物 | 攻击 | |
---|---|---|---|
Small Mario | Mario Super Mario/+1000 | Dead/- | -/- |
Super Mario | Fire Mario/+1000 | Small Mario/- | -/- |
Fire Mario | -/+1000 | Small Mario/- | -/发射火球 |
Dead Mario | -/- | -/- | -/- |
注:-/-表示不存在这种状态转移
状态机编程仅是分析对象的一种思路,并不与特定代码和编程语言想绑定,如果它可以帮你理清对象状态的变化特性,那么这就是一种有效的方法,反之,如果你描述的状态机纷繁复杂,无法帮你缕清思路,则可能这种方法并不适合你当前的问题。