Qurak

Make Code Talk

0%

FSM 编程实现

目录

  • 有限状态机 FSM
  • 一个简单的 C++ 实现

1 有限状态机 FSM

有限状态机是对一个对象的行为以及状态的抽象描述。举个例子,存在一个对象,默认状态为 A,当有一个事件 E1 发生的时候,则对象从 A 状态进入到 B 状态。此时有另一个事件 E2 发生,对象从 B 状态进入 C 状态。其中 A,B,C 状态在接收到 E3 的时候均会跳转到 A 初始状态。在这个例子中,对象就相当于一个 FSM 系统,对不同的事件做出不同的反应(进入不同的状态,触发状态中的行为)。

如果我们将研究对象设置为 FSM 中的每个状态,那么针对每一个状态,都有四个属性:当前状态(Current State),等待接受的事件(Event),接受事件而到达的下一个状态(Next State)以及当前状态的所执行的操作(Action)。

image-20220228224600501

用图表示的方法固然很直观,但是当状态数量以及事件数量比较多的时候,图则比较乱,因此有时候建议用表格的形式

Current State Event Next State
A E1 B
B E2 C
A E3 A
B E3 A
C E3 A

总结一下,状态机可以认为对对象行为模式的一种抽象表示方法,其关键在于需要分解每一个状态,并利用事件的触发来完成状态的转移。状态机可以用图的方式绘制出来,也可以是用状态转换表的形式画出来(有利于后续的编程)

2 一个简单的 C++ 实现

这里给出一个 C++ 的实现思路,我自己的想法是想让构建 FSM 的过程变得直接,直观。因此我采用 template + enum 来实现,只需要使用 enum 构建出状态集合和事件集合,在初始化的时候附上初始状态(也称开始状态)就可以快速构成一个简单的状态机。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
template<typename S, typename E>
class easyFSM
{
public:
// constructor
easyFSM(S StartState):_curState(StartState){}
// output the current state
S CurState(){return _curState}
// bind
void bind(S curState, S nextState, E event, void (*action)());
// send a event to FSM to change the current state
void handleEvent(E event);
private:
// def the function pointer
typedef void ACTION_PTR(void);
// To set up the state transfer table,
// I use the item to keep neccessary information.
class item
{
...
private:
S _curState;
E _event;
S _nextState;
ACTION_PTR *_action;
}
typedef std::vector<item> VECITEM;
S _curState; // the current state of FSM
VECITEM _itemlist; // to make up all states
}

You can check on my github for more details of code: https://github.com/ChrisZ-NJU/easyFSM