第7章:状态图 (State Diagram) - 建模对象生命周期(纯小白版)
状态图(StateDiagram)是用于描述对象或系统生命周期中状态变化的重要工具。本课程详细介绍了使用Mermaid绘制状态图的方法:1)通过stateDiagram-v2声明图表;2)定义状态(隐式/显式)和状态转换(带事件标签);3)标识起始([*])和结束状态;4)构建复合状态(嵌套子状态);5)处理并发状态(使用分割线--);6)添加注释(note)和选择点(<<choice
开始这堂关于状态图 (State Diagram) 的课程。这是一种非常强大的图表,专门用来描述一个对象或系统在其生命周期内,所经历的各种状态以及状态之间转换的规则。
如果说流程图是描述一个“过程”,那么状态图就是描述一个“事物”的“一生”。
本课程的所有示例都非常简短,强烈建议您打开 Mermaid 官方的在线编辑器 mermaid.live
,一边学习一边亲手尝试下面的每一个小步骤。
第二部分:常用图表绘制
第7章:状态图 (State Diagram) - 建模对象生命周期
好比说:我们来思考一个最简单的“电灯”的生命周期。它只有两种状态:“关”和“开”。而导致状态变化的事件是“按开关”。状态图就是用来清晰地描绘这种关系的。
7.1 状态图声明与状态定义 (stateDiagram-v2
)
第一步:声明图表类型
任何一个状态图,都必须以 stateDiagram-v2
这个关键字开头。v2
代表这是新版本的状态图语法,功能更强大,我们应该始终使用它。
我们先写下这最基本的第一行:
代码段
stateDiagram-v2
这行代码会创建一个空白的状态图画布。
第二步:隐式地定义状态
最简单的方式,就是直接在描述“转换”关系时提到状态的名字,Mermaid会自动创建它们。
代码段
stateDiagram-v2
Off --> On
这行代码就自动为我们创建了两个状态:Off
(关)和 On
(开)。
第三步:显式地定义状态
当你需要为状态提供一个更具描述性的别名,或者定义更复杂的复合状态时,可以使用 state
关键字。
语法: state "要显示的文本" as 状态ID
代码段
stateDiagram-v2
state "等待中" as Waiting
state "运行中" as Running
这里我们定义了两个状态,它们的ID是Waiting
和Running
,但在图上会显示为中文“等待中”和“运行中”。
7.2 定义状态转换 (-->
)
1. 核心概念
状态转换,指的是一个对象从一个状态迁移到另一个状态的过程。这个过程通常是由一个事件 (Event) 触发的。
2. 一步一步定义转换
第一步:使用箭头 -->
我们使用箭头 -->
来表示一个状态可以转换到另一个状态。
代码段
stateDiagram-v2
Off --> On
On --> Off
这表示“关”状态可以转换到“开”状态,反之亦然。
第二步:为转换添加标签(描述事件)
这是状态图中至关重要的一步。我们需要在箭头上添加文本,来说明是什么事件导致了这个状态转换。
语法: 状态1 --> 状态2 : 事件描述
代码段
stateDiagram-v2
Off --> On : press_switch
On --> Off : press_switch
现在这个图的含义就非常清晰了:无论是从“关”到“开”,还是从“开”到“关”,触发的事件都是 press_switch
(按开关)。
7.3 定义起始与结束状态 ([*]
)
1. 核心概念
一个完整的生命周期,应该有明确的起点和终点。
好比说:一个订单的生命周期,从“创建”(起点)开始,到“已完成”或“已取消”(终点)结束。
2. 一步一步定义
第一步:定义起始状态
使用 [*]
符号代表起始点,它是一个实心圆。
代码段
stateDiagram-v2
# 从起始点转换到“待支付”状态
[*] --> PendingPayment
第二步:定义结束状态
同样使用 [*]
符号代表结束点,它是一个带圆圈的实心圆。
代码段
stateDiagram-v2
# “已完成”状态可以转换到结束点
Completed --> [*]
# “已取消”状态也可以转换到结束点
Cancelled --> [*]
第三步:组合一个简单的生命周期
代码段
stateDiagram-v2
[*] --> PendingPayment : create_order
PendingPayment --> Processing : pay
Processing --> Completed : ship
Completed --> [*]
这个图清晰地描述了一个订单从创建到完成的“快乐路径”。
7.4 复合状态(嵌套)
1. 核心概念
有时候,一个状态本身可能就非常复杂,它内部还包含自己的一套子状态。这种“状态中的状态”,就叫做复合状态。
好比说:“听音乐”是手机的一个状态。但在“听音乐”这个大状态里面,又可以细分为“正在播放”、“已暂停”、“正在缓冲”这几个子状态。
2. 一步一步定义复合状态
第一步:使用 state
和花括号 {}
定义复合状态
代码段
stateDiagram-v2
# 定义一个名为 "MusicPlayer" 的复合状态
state "听音乐" as MusicPlayer {
# 嵌套的子状态图将写在这里
}
第二步:在复合状态内部定义子状态和转换
代码段
stateDiagram-v2
state "听音乐" as MusicPlayer {
# 子状态图也有自己的起始点
[*] --> Paused
Paused --> Playing : play_button
Playing --> Paused : pause_button
}
第三步:定义进出复合状态的转换
代码段
stateDiagram-v2
[*] --> Idle : open_app
state "听音乐" as MusicPlayer {
[*] --> Paused
Paused --> Playing : play_button
Playing --> Paused : pause_button
}
Idle --> MusicPlayer : select_song
MusicPlayer --> Idle : close_player
现在,这个图就完整地描述了:应用打开后进入Idle
状态,选歌后进入MusicPlayer
这个大状态,并在其内部的Paused
和Playing
子状态间切换,最后关闭播放器又回到Idle
状态。
7.5 并发状态(Forks and Joins)
1. 核心概念
并发状态用于描述一个系统可以同时处于多个独立的状态区域。
好比说:你在“工作”这个大状态中,可以同时处于“用键盘打字”和“用耳机听歌”这两个并行的子状态。这两个子状态互不干扰,同时发生。
2. 一步一步定义并发状态
第一步:使用 --
分割线
在复合状态内部,我们使用 --
分割线来创建并行的区域。
第二步:定义一个包含并发区域的复合状态
代码段
stateDiagram-v2
state "文档处理中" as Processing {
# 使用 -- 分割成两个并发区域
ImageHandling
--
TextHandling
}
第三步:为每个并发区域定义自己的状态流
代码段
stateDiagram-v2
[*] --> Processing
state "文档处理中" as Processing {
state "图片处理" as ImageHandling {
[*] --> Resizing
Resizing --> Compressing
Compressing --> [*]
}
--
state "文本处理" as TextHandling {
[*] --> SpellCheck
SpellCheck --> Formatting
Formatting --> [*]
}
}
Processing --> [*]
这个图表示,当进入“文档处理中”状态后,“图片处理”和“文本处理”这两条流水线会同时开始工作。
7.6 为状态和转换添加注释与描述
第一步:为状态添加描述
你可以在状态框的标题下方,为其添加更详细的文字描述。
语法:状态ID : 描述文字
代码段
stateDiagram-v2
state "正在验证" as Validating
Validating : 正在调用第三方API
Validating : 检查用户凭证...
这会在“正在验证”这个状态框里,显示出下面两行描述文字。
第二步:为转换添加注释 (note
)
如果你想为某个状态或转换添加一段更长的、像便利贴一样的注释,可以使用note
。
语法:note [right of | left of] 状态ID : 注释内容 end note
代码段
stateDiagram-v2
[*] --> Idle
note right of Idle
这是系统的初始状态。
它正在等待外部事件的触发。
end note
这会在Idle
状态的右边,生成一个带箭头的注释框。
7.7 选择点 (Choice Points)
1. 核心概念
选择点用于表示一个基于条件判断的动态转换。它允许一个流程在离开当前状态后,根据不同的条件,进入到不同的下一个状态。
好比说:一个订单在“已支付”状态后,会进入一个“检查点”(选择点)。在这个检查点,系统会判断“订单金额是否大于100元”。如果是,则进入“需要人工审核”状态;如果否,则直接进入“自动发货”状态。
2. 一步一步定义选择点
第一步:使用 <<choice>>
定义一个选择点状态
代码段
stateDiagram-v2
# C1是我们给这个选择点起的名字
state C1 <<choice>>
它在图上会被渲染成一个菱形。
第二步:将流程引导至选择点
代码段
stateDiagram-v2
Paid --> C1 : check_amount
state C1 <<choice>>
第三步:从选择点引出带条件的转换
条件的语法是 [条件描述]
。
代码段
stateDiagram-v2
state C1 <<choice>>
C1 --> ManualReview : [amount > 100]
C1 --> AutoShip : [amount <= 100]
第四步:组合成一个完整的例子
代码段
stateDiagram-v2
[*] --> Paid
Paid --> C1 : check_amount
state C1 <<choice>>
C1 --> ManualReview : [amount > 100]
C1 --> AutoShip : [amount <= 100]
ManualReview --> AutoShip : approved
AutoShip --> [*]
这个图清晰地展示了,Paid
状态之后,流程会根据金额大小,走向两条不同的路径。
更多推荐
所有评论(0)