Files
obsidian/软件需求分析/各章笔记/第06章-状态图与活动图.md

435 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第6章 状态图与活动图
> **考试重要度**:★★★★★
> **核心内容**:状态图的组成(状态/转移/事件)、四种事件类型、活动图元素(泳道/分支/分叉汇合、状态vs活动的区别
---
## 📢 从手机理解状态图和活动图
💬 你的手机有以下**状态**:闲置 → 解锁 → 使用中 → 锁屏 → 闲置。
每个状态之间的切换需要**事件**触发:点击屏幕、输入密码、按电源键……
这就是**状态图**——描述**一个对象**在生命周期内的状态变化。
而**活动图**描述的是**一个流程**:比如"打电话"这个活动——打开拨号盘 → 输入号码 → 点击拨号 → 通话 → 挂断。这其中可能涉及多个对象。
---
## 💡 一、状态图的核心元素
### 状态图三要素
```
┌──────────┐ 事件[条件]/动作 ┌──────────┐
│ 状态A │ ─────────────────→ │ 状态B │
└──────────┘ └──────────┘
```
| 要素 | 说明 |
|------|------|
| **状态** | 对象在某个时刻所处的条件或状况 |
| **转移** | 从一个状态到另一个状态的变化 |
| **事件** | 触发状态转移的原因 |
### 状态的组成
```
┌────────────────────────┐
│ 状态名 │
├────────────────────────┤
│ entry / 入口动作 │
│ exit / 出口动作 │
│ do / 持续活动 │
│ 内部转移(不离开状态) │
└────────────────────────┘
```
### 组合状态和历史状态
💬 **组合状态**:一个大状态里面还有小状态的变化过程。
> 例:汽车"行驶"状态里面还有子状态:加速、匀速、减速。
💬 **历史状态**:记住离开组合状态时处于哪个子状态,回来后可以接着来。
> 例:数据备份——中途被打断,恢复后可以继续从断点备份。
---
## 💡 二、四种事件类型
| 事件类型 | 含义 | 举例 |
|----------|------|------|
| **调用事件** | 一个方法的调用 | `借书()` → 借书证从"可借"变为"不可借" |
| **信号事件** | 一个异步发送的信号实体 | 遥控器发出"Play"信号 → CD机进入"播放"状态 |
| **变化事件** | 布尔表达式值发生变化 | 温度>100℃ → 锅炉进入"报警"状态 |
| **时间事件** | 到达某个时间点或时间段 | 30秒超时 → 从"拨号"回到"就绪" |
### 🔑 调用事件 vs 信号事件
| 对比 | 调用事件 | 信号事件 |
|------|----------|----------|
| **本质** | 调用一个方法 | 发送一个信号对象 |
| **发送方** | 可以是自己或其他对象 | 只能是其他对象 |
| **特点** | 可扩展性弱 | 信号类可泛化,扩展性强 |
💬 例CD唱机——如果各种遥控信号作为遥控器的属性变化事件增加新信号就要修改遥控器类。如果把遥控信号建模为信号类信号事件增加新信号只需新增子类不用改遥控器。
---
## ✍️ 边学边练(一)
**题目**:画出"图书"对象的状态图。
需求:新书购买后需编码才能入库。入库后可借出。借出的书不能被再借出。还书后可再借出。图书破损或过时必须下架,下架后不能再借出。
**答案:**
**状态**:未编码 → 可借(在库) → 已借出 → 可借(在库) → 已下架
**转移**
- 未编码 → 可借:`编码()`
- 可借 → 已借出:`借出()`
- 已借出 → 可借:`还书()`
- 可借 → 已下架:`下架()` [破损或过时]
- 已借出 → 已下架:`下架()` [破损或过时]
⚠️ 注意:状态图中有两个状态必须有"下架"转移(从可借和已借出都可以下架)。
---
## 💡 三、活动图的核心元素
### 活动图的基本元素
| 元素 | 说明 | 画法 |
|------|------|------|
| **活动** | 一个执行步骤 | 圆角矩形 |
| **起点** | 流程的开始 | 实心圆 ● |
| **终点** | 流程的结束 | 圆圈加实心圆 ⊙ |
| **分支** | 根据条件选择路径 | 菱形 ◇ |
| **分叉/汇合** | 并发执行的开始/结束 | 粗横线 |
| **泳道** | 标明活动由谁负责 | 纵向分区 |
| **对象流** | 活动之间传递的对象 | 带箭头的虚线 |
### 📌 活动图各元素的画法速查
> 这一节把活动图中**所有画图元素**用字符画列出来,画活动图直接照搬即可。
#### ① 起点 —— 实心圆 ●
```
```
#### ② 终点 —— 圆圈加实心圆 ⊙(也称"牛眼"
```
```
#### ③ 活动Activity—— 圆角矩形
```
╭───────────╮
│ 登录验证 │ ← 文字描述这一步做什么
╰───────────╯
```
#### ④ 转移箭头 —— 实线 + 开放箭头
```
╭───────────╮
│ 活动 A │
╰─────┬─────╯
⇨ 实线 + 开放箭头(类似异步消息)
╭─────┴─────╮
│ 活动 B │
╰───────────╯
```
#### ⑤ 分支Decision—— 菱形 ◇ + 监护条件
```
╭───────────╮
│ 活动 A │
╰─────┬─────╯
◇ ← 菱形(决策点)
[是] ╲[否]
╭─────╮ ╭─────╮
│ 活动B │ │ 活动C │
╰─────╯ ╰─────╯
◇ ← 合并点(多个分支汇合)
╭─────┴─────╮
│ 活动 D │
╰───────────╯
```
#### ⑥ 分叉Fork/ 汇合Join—— 粗横线
> **分叉**:一条路径分成多条并发执行。
> **汇合**:多条并发路径汇合成一条。
```
╭───────────╮
│ 活动 A │
╰─────┬─────╯
━━━━━━━━━━ ← 粗横线(分叉点)
│ │
⇨ ⇨
╭─────╮ ╭─────╮
│活动B│ │活动C│ ← B和C并发执行
╰──┬──╯ ╰──┬──╯
⇨ ⇨
│ │
━━━━━━━━━━ ← 粗横线(汇合点)
╭─────┴─────╮
│ 活动 D │ ← B和C都完成后才继续
╰───────────╯
```
#### ⑦ 泳道Swimlane—— 纵向分区
> 标明每一步由**哪个对象/角色**负责。
```
┌──────────┬──────────┬──────────┐
│ 客户 │ 业务员 │ 系统 │
│ (泳道1) │ (泳道2) │ (泳道3) │
├──────────┼──────────┼──────────┤
│ │ │ │
│ ● │ │ │ ← 起点
│ ⇩ │ │ │
│ ╭───╮ │ │ │
│ │下单│ │ │ │ ← 客户下单
│ ╰─┬─╯ │ │ │
│ │ │ │ │
│ ⇨ │ │ │
│ ╭───╮ │ │
│ │接单│ │ │ ← 业务员接单
│ ╰─┬─╯ │ │
│ │ │ │
│ ⇨ │ │
│ ╭───╮ │
│ │处理│ │ ← 系统处理
│ ╰─┬─╯ │
│ │ │
└──────────┴──────────┴──────────┘
⊙ ← 终点
```
#### ⑧ 对象流Object Flow—— 虚线 + 箭头
> 表示活动之间**传递的对象**(数据)。
```
╭───────────╮ ┌──────────┐
│ 提交订单 │ ── ─ ─▶│ 订单 │ ← 虚线 + 箭头
╰───────────╯ └──────────┘
⇨ (对象流也指向下一个活动)
╭─────╮
│ 付款 │
╰─────╯
```
⚠️ **注意**:对象本身画成**矩形**(不是圆角矩形),虚线箭头表示"这个活动产生/使用了这个对象"。
#### ⑨ 完整活动图示例(不带泳道)
```
● 起点
╭─────────╮
│ 开始借书 │
╰────┬────╯
╭─────────╮
│ 扫描图书 │
╰────┬────╯
╭─────────╮
│ 扫描借书证│
╰────┬────╯
◇ 判断
[可借] ╲[不可借]
╭─────╮ ╭───────╮
│ 借出 │ │ 提示原因│
╰──┬──╯ ╰───┬───┯
⇩ ⇩ │ (汇合)
│ │ │
╰───◇ 汇合 ◇────╯
╭─────────╮
│ 结束 │
╰─────────╯
⊙ 终点
```
#### ⑩ 状态图元素的画法
> 状态图和活动图有些元素是**共用的**(起点/终点/转移箭头)。
**状态**:圆角矩形,**可带分区**(状态名 / 内部活动)
```
╭─────────────────────╮
│ 待机中 │ ← 第一行:状态名
├─────────────────────┤
│ entry / 初始化 │ ← 入口动作
│ do / 持续活动 │ ← 持续活动
│ exit / 清理 │ ← 出口动作
╰─────────────────────╯
```
**转移Transition**
```
╭──────────╮ 事件[条件]/动作 ╭──────────╮
│ 状态A │ ─────────────────▶ │ 状态B │
╰──────────╯ ╰──────────╯
格式:事件名[监护条件]/动作
例: 借出() / 可借数-1
```
**历史状态 H**:圆圈里写 H记录离开时的子状态
```
╭──────────╮
│ 复合状态 │
╰────┬─────╯
(H) ← 历史状态圆圈里写H
╭──────╮ ╱│╲
│ 子1 │◀─(H)─▶│ 子2 │ ← 回来时回到H记录的子状态
╰──────╯ ╰─────╯
```
🔑 **一句话记忆口诀**:实心圆是起点,牛眼是终点;圆角矩形是活动,菱形是分支;粗横线是分叉汇合,泳道是纵向分区,对象是普通矩形+虚线箭头。
---
### 🔑 状态 vs 活动(必考区别!)
| 对比 | 状态 | 活动 |
|------|------|------|
| **本质** | 对象所处的**境况** | 一段程序代码的**执行过程** |
| **持续时间** | 可以很长(等待状态) | 相对短暂(执行完就结束) |
| **关系** | 是活动执行后的**结果** | 是导致状态变化的**原因** |
| **关注对象** | 一个对象 | 可以涉及多个对象 |
| **UML图** | 状态图 | 活动图 |
💬 **比喻**:做菜的过程(洗菜→切菜→炒菜→装盘)是**活动**;菜做完了变成"已做好"是**状态**。
### 活动图的两种用途
1. **对业务流程建模**(不带泳道)—— 用于需求分析,描述用例的工作流程
2. **对系统操作建模**(带泳道)—— 用于系统设计,把步骤落实到具体对象
---
## ✍️ 边学边练(二)
**题目**:画出"借书"用例的带泳道活动图。
流程:图书管理员录入图书条码和借书证号 → 系统判断借书证能否借书 → 若不能,显示原因并结束 → 若能,生成借阅记录,修改可借本数。
**答案:**
**泳道划分**:图书管理员 | 系统
```
图书管理员泳道:
录入条码和借书证号 →
系统泳道:
判断能否借书 → [不能] → 显示原因 → 结束
→ [能] → 生成借阅记录 → 修改可借本数 → 结束
```
⚠️ 关键:分叉用菱形,两个分支最终汇合到结束。
---
## 💡 四、状态/活动与用例/方法的关系
### 状态与方法、用例的联系
- 一个方法的执行 → 属性值改变 → 对象进入新**状态**
- 对象处于不同状态 → 影响后续哪些**用例**可以执行
- 一个对象完整的状态图 = 多个用例的顺序图**融合**
### 活动与方法、用例的联系
- 一个**活动** = 一个方法中的部分(或全部)语句执行
- 一个方法可能需要多个活动来完成
- 一个**用例** = 若干个活动,通常一个用例对应一个活动图
---
## ✍️ 边学边练(三)
**题目**:借书证的状态图中有"可借书"和"不可借书"状态。问:
1. "借书"操作对应什么事件类型?
2. 从"不可借书"转回"可借书"需要什么事件?
3. "借书证"的状态图与哪些用例有关?
**答案:**
1. **调用事件**——"借书"本质上是对借书证对象调用借书方法
2. **还书事件**——读者还书后借书证的可借本数减1重新变为可借
3. 与"借书""还书""挂失借书证"等用例有关。这些用例的顺序图融合起来,就构成了借书证的完整状态图
---
## 📝 章末自测
**1. 填空题**
- 状态图描述的是( ____ )个对象的状态变化
- 四种事件类型是:调用事件、( ____ )、( _____ )、时间事件
- 活动图中的菱形表示( ____ ),粗横线表示( ___
**2. 判断题**
- ( ) 状态图和活动图都可以描述多个对象的交互
- ( ) 信号事件比调用事件更易于扩展
- ( ) 一个活动可能跨越多个泳道
- ( ) 带泳道的活动图用在系统设计阶段
**3. 简答题**
- 简述状态和活动的区别。
- 什么情况下应该用状态图,什么情况下应该用活动图?
**答案:**
**填空题**:一(单个);信号事件、变化事件;分支、分叉/汇合
**判断题**
- ❌ 状态图只描述一个对象
- ✅ 信号类可继承扩展
- ❌ 每个活动只属于一个泳道
- ✅ 带泳道用于设计阶段
**简答题**
- 状态是对象的境况(活动执行后的结果),可以持续很长时间;活动是代码的执行过程,相对短暂。状态变化由活动引起。
- 状态图:描述一个对象生命周期内的状态变迁(如订单状态、借书证状态)。活动图:描述一个业务流程或算法步骤(如取款流程、登录验证流程)。
---
> 🔗 上一篇:[第5章 顺序图与协作图](第05章-顺序图与协作图.md) | 下一篇:[第7章 组件图与部署图](第07章-组件图与部署图.md)