本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。
本系列描述我对书中内容的理解。
书中大量使用了 UML 表示法,之前讲述过了 类图
,这篇文章讲述 状态图
。
有限状态机
有限状态机
是一个模型,在编程领域非常重要和有用。有限状态机的三个特征:
- 状态是有限的
- 任一时刻,只处在一种状态中
- 在某种事件触发下,会从一种状态转换到另一种状态。
状态图
状态图
是九种常见 UML 图中的一种,它是一个有向图,由 状态
和 转换
组成。状态图常用于对类和用例的 行为
进行建模,类和用例在某种 状态
中等待,直到感兴趣的 事件
发生(wait in a state until an event of interest occurs)。此时,处理 事件
、执行 动作
,并且 转换
状态。
有向图
是一种特殊的图,它的边具有起点和终点的概念,不能逆转方向。有向图适合描述具有明确方向的关系。
状态
在 UML 中,状态
用圆角矩形表示。
状态可能包含 进入动作
、退出动作
和 内部转换
。
- 进入动作:仅当进入状态时,执行一次进入动作;
- 退出动作:仅当退出状态时,执行一次退出动作;
- 内部转换:内部转换不会改变状态机的状态,只是在其内部逻辑中进行了某种处理或计算。举例来说明:假设有一个状态机,它有两个状态:状态A和状态 B。当状态机处于状态 A 时,如果发生内部转换,它仍然保持在状态 A,而不会进入状态 B。这个内部转换可能是在状态A的某个条件下触发,并进行一些内部处理或计算,但不会改变状态机的状态。
状态是可以嵌套的,称为 复合状态
。
在 UML 中,初始状态使用实心圆点表示,终止状态使用内嵌圆点表示:
动作
动作
是指在状态转换过程中需要执行的操作或行为。动作是与状态相关联的,当状态机从一种状态转换到另一种状态时,会执行相应的动作。动作一般包括:进入动作、退出动作和转换动作。
动作的执行顺序是:先执行前一个状态的 退出
动作,然后执行 转换
动作,最后执行后续状态的 进入
动作。
常见的动作有:
- 函数调用,如
foo();
- 基本动作,如
x += 10;
- 生成事件
转换和事件
状态机中的 转换
指的是状态之间的迁移,即从一个状态转换到另一个状态。转换由特定的 事件
触发,并且可以在执行一系列动作后完成。
事件
是指能够触发状态机行为变化的情况或条件。事件可以是外部的,例如用户输入、定时器超时、接收到其他系统的消息等;也可以是内部的,例如变量值的改变、程序流程的控制转移等。当事件发生时,状态机会根据当前状态和事件的类型执行相应的动作,并可能触发状态转换。
在状态机中,转换和事件是相互关联的。事件是触发状态转换的条件或原因,而转换则是状态机从一个状态转移到另一个状态的机制。
在 UML 中,转换
是一个带箭头的线(→),始于前一个状态,终于后一个状态。转换通常具有可选的 事件签名
和 转换动作列表
,基本形式是:
转换事件名称 ( 参数列表 ) [ 监护条件 ] / 转换动作列表 转换事件名称 (参数列表) [监护条件] / 转换动作列表 转换事件名称(参数列表)[监护条件]/转换动作列表
其中,转换事件名称
可以为空。监护条件
是一个布尔表达式,只能为真或假,也可以为空。只有发生了事件,并且 监护条件
为真时,进行状态转换,此时执行 转换动作列表
,转换动作列表也可以为空。
如果没有转换事件,则认为是“无条件转换”,一旦前一个状态的进入动作执行完成,立即触发转换。
比如一个事件是 按下按键
,监护条件是 按键是取消键
,转换动作是 显示消息:取消
。那么每当有按键按下时,触发事件,如果按键是“取消键”则显示一条消息,否则忽略这次触发事件。