状态机应该是最常用的设计模式了,而且在各种开发语言中,,甚至是硬件描述语言都常用。
状态机简单概念
状态机非常简单和直观,有两个基本概念:
- 状态(State):一个对象在某个时刻或某段时间,具有某种稳定的属性,就称其在某个状态。例如灯有“亮”、“灭”两种状态,门有“开”、“关”两种状态等。
- 迁移(Transition):从一种状态变到另一种状态就叫迁移。例如灯从亮到灭、从灭到亮,门从开到关、从关到开。
把状态和迁移画出来就成了状态图。从上面的例子也可以想到,有时迁移不会自动发生,例如门从关到开(也就是开门)是因为发生了“要出门”这个条件,并且迁移伴随着动作,也就是开门这个动作。
那么就可以画一个简单的状态图,用/前表示发生条件,/后表示动作
PS.这里的重点为了表现状态机的概念,实际问题中条件和动作可能更加复杂,例如需要区分准入条件和准出条件、进入动作和退出动作等。
状态机设计模式
当需要描述的对象或问题存在多种状态以及多种条件判断时,就可以考虑状态机模式了。画出状态图可以非常直观理解其变化。
状态机有横写和竖写两种方式,区别在于考虑的重点是在状态还是迁移上。有时对象是状态多但迁移条件简单,有时是状态少但迁移条件多。根据写出的代码长度就能看出来了,不需要特别区分。
上面门的例子用状态机来实现。
1 | typedef enum { |
另一种方式,
1 | void want_out(void) { |
像之前所说的,标准的状态机模式实现可能还包括很多其他条件和动作,但在实践中通常不会每个迁移每个状态都会用到所有的条件和动作,因此只需要记住状态和迁移的概念,在实现中只写用到的部分就可以了。