Files
obsidian/软件需求分析/各章笔记/第05章-顺序图与协作图.md

386 lines
15 KiB
Markdown
Raw 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.
# 第5章 顺序图与协作图
> **考试重要度**:★★★★
> **核心内容**顺序图的四个核心元素、六种消息类型、调用消息vs异步消息、顺序图与协作图的对比
---
## 📢 从打电话理解交互图
💬 你打电话给朋友借钱,整个对话过程是这样的:
```
你 → 拨号 → 朋友接电话 → 你说"借我500" → 朋友说"好" → 你挂电话
```
这就是一个**交互过程**——两个对象之间按时间顺序传递消息。在UML中我们用**顺序图**和**协作图**来描述这个过程。
---
## 💡 一、顺序图的四个核心元素
```
┌─────────────────────────────────────────────┐
│ 对象 生命线 控制焦点(激活期) │
│ ┌───┐ │ ┌──┐ │
│ │obj│ │ │ │ │
│ └─┬─┘ │ └──┘ │
│ │- - - - - │- - - - - - - - - - - │
│ │ │ 消息→ │
│ │ │ ┌──┐ │
│ │ │ │ │ │
│ │ │ └──┘ │
└─────────────────────────────────────────────┘
```
| 元素 | 说明 | 画法 |
|------|------|------|
| **对象** | 类的实例,参与交互的实体 | 矩形,顶部放置 |
| **生命线** | 对象存在的时间线 | 从对象向下延伸的虚线 |
| **控制焦点**(激活期) | 对象正在执行操作的时间段 | 生命线上的细长矩形条 |
| **消息** | 对象之间的一次通信 | 带箭头的直线 |
---
## 💡 二、消息的语法格式
消息的完整格式:
```
[前置条件] [警戒条件] [序号] [返回值:=] 消息名([参数列表])
```
例子:
```
2: display(x, y) → 简单消息序号2
1.3.1: p := find(specs) → 嵌套消息,有返回值
[x<0] 4: invert(x, color) → 条件消息
3.1*: update() → 循环消息
```
### 消息序号的含义
- `1, 2, 3` — 顺序发送的消息
- `1.1, 1.2, 1.3` — 消息1内部的嵌套调用1.1必须在1完成之前完成
- `A1, B1` — 并发线程中的消息
---
## 💡 三、六种消息类型
| 消息类型 | 说明 | 画法 |
|----------|------|------|
| **调用消息** (同步) | 发送者等待接收者完成才继续 | 实线实心箭头 → |
| **异步消息** | 发送者不等待,继续执行 | 实线开放箭头 ⇢ |
| **返回消息** | 从调用返回 | 虚线开放箭头 ⇢ |
| **反身消息** | 发给自己 | 绕回自己的箭头 |
| **阻止消息** | 接收者不能立即接收就放弃 | 特殊标记 |
| **超时消息** | 等待指定时间,超时就放弃 | 特殊标记 |
### 📌 消息类型的画法速查
> 这一节把六种消息类型的**实际画法**用字符画的形式画出来,光看箭头符号记不住的话,照着画就行。
#### ① 调用消息(同步)—— 实线 + 实心三角箭头
```
┌───┐ ┌───┐
│ A │ ──────────────────▶│ B │ ← 实线 + 实心三角
└───┘ └───┘
同步等B做完再回来
```
#### ② 异步消息 —— 实线 + 开放箭头V形
```
┌───┐ ┌───┐
│ A │ ─────────────────⇨ │ B │ ← 实线 + 开放箭头
└───┘ └───┘
异步:发完就接着干自己的事
```
#### ③ 返回消息 —— 虚线 + 开放箭头
```
┌───┐ ┌───┐
│ A │ ◀─ ─ ─ ─ ─ ─ ─ ─ ─ │ B │ ← 虚线 + 开放箭头
└───┘ └───┘
返回值(可省略不画)
```
#### ④ 反身消息 —— 自己绕回来
```
┌───┐
│ A │ ───┐
└───┘ │
│ │
◀─────┘
(即"对象调用自己的方法"
```
#### ⑤ 阻止消息 —— 实线 + 叉 ✕
> 接收方当时忙,**直接放弃**这次调用。
```
┌───┐ ┌───┐
│ A │ ─────────────────╳ │ B │ ← 实线 + 叉
└───┘ └───┘
B没空A立刻放弃不等
```
#### ⑥ 超时消息 —— 实线 + 倒三角 ⏳
> 等待指定时间,**超时就放弃**。
```
┌───┐ ┌───┐
│ A │ ─────────────────⏳ │ B │ ← 实线 + 倒三角
└───┘ └───┘
等一段时间后超时
```
### 📌 完整顺序图示例
把所有消息类型都画在一张图里看效果:
```
客户 ATM界面 账户
┌───┐ ┌───┐ ┌───┐
│ │ │ │ │ │
╱│╲ │ ╱│╲ │ ╱│╲ │
╲ │ ╲ │ ╲ │
┌───┐ ┌───┐ ┌───┐
│ │ │ │ │ │
│ │ 1: 取款(500) │ │ │ │ ← ① 调用消息
│ ├──────────────▶│ │ │ │
│ │ │ │ 2: 查询余额() │ │ ← ① 调用消息
│ │ │ ├───────────────▶│ │
│ │ │ │ │ │
│ │ │ │ ◀─ 3: 余额 ─── │ │ ← ③ 返回消息
│ │ │ │ │ │
│ │ │ │ 4: 扣款(500) │ │ ← ① 调用消息
│ │ │ ├───────────────▶│ │
│ │ │ │ │ │
│ │ 5: 出钞 │ │ │ │ ← ② 异步消息
│ │◀─ ─ ─ ─ ─ ─ ─│ │ │ │
│ │ │ │ │ │
```
### 📌 组合片段Combined Fragment速查
> 当顺序图比较复杂时,可以用**框选区域**的方式来表达条件、循环、并行等逻辑。
```
┌────────────── alt: 余额判断 ──────────────┐
│ │
│ │ 条件A: │
│ │ 4.1: 扣款(amount) ──▶ │
│ │ │
├────────────────────────────────────────────┤
│ │
│ │ 条件B: │
│ │ 4.2: 显示"余额不足" ──▶ │
│ │
└────────────────────────────────────────────┘
```
常用组合片段关键字:
| 关键字 | 含义 | 用途 |
|--------|------|------|
| `alt` | 抉择(多选一) | 相当于 if-else |
| `opt` | 可选(满足才执行) | 相当于单分支 if |
| `loop` | 循环 | 相当于 for/while |
| `par` | 并行 | 多个事件流同时进行 |
| `neg` | 非法 | 描述不允许发生的场景 |
| `critical` | 关键 | 必须原子执行的区域 |
---
### 📌 协作图Communication Diagram的画法
> 协作图 = 顺序图的"空间版"——**没有生命线**,但消息必须**带完整序号**。
```
1: 输入金额
客户 ──────────────▶ ATM界面
○ │
╱│╲ │ 2: 查询余额
╲ ▼
账户
╱│╲
│ 3: 返回余额
◀───── 4.1*: 出钞 ─────┘
(出钞多次循环)
```
**协作图的关键特征**
- 对象之间的**连线**(关联)作为消息传递的路径
- 消息的**前缀序号**必须完整(`1`, `1.1`, `1.1.1`
- `{new}` 标签表示对象在交互中被创建
- `{destroy}` 标签表示对象在交互中被销毁
```
┌──────────┐ ┌──────────┐
│ :Order │ │ :Payment │
│{new} │ 1: 创建支付 │ │
└──────────┘ ────────────────▶ └──────────┘
│ {destroy}
(被销毁)
```
🔑 **一句话记忆口诀**实心三角是同步开放箭头是异步返回用虚线开放箭头反身消息自己绕alt/loop/par 框选区域,条件循环并行都能搞。
---
## 🔑 调用消息 vs 异步消息(必考!)
| 对比维度 | 调用消息 | 异步消息 |
|----------|----------|----------|
| **发送者行为** | 发出后**停下来等** | 发出后**继续干活** |
| **控制焦点** | 发送者出现等待(重叠矩形条) | 发送者不等待 |
| **典型场景** | 查询数据库(必须等结果) | 写日志文件(可以后台进行) |
| **返回消息** | 必有返回,可以省略不画 | 如果是过程调用必有返回 |
💬 **比喻**
- 调用消息像**打电话**——你说一句,等对方回一句。
- 异步消息像**发微信**——你发一条,继续干自己的事,对方看到再回。
---
## 💡 四、顺序图的两种形式
| 形式 | 说明 |
|------|------|
| **一般形式** | 包含条件、分支、循环,描述所有可能的场景 |
| **实例形式** | 只有一个具体的场景,没有任何分支和循环 |
💬 例:取款的一般形式包含"余额够"和"余额不够"两个分支;而某次具体取款(余额够)就是实例形式。
### 条件消息和循环消息的表达
**两种方法**
1. 在消息上直接标注:`[x>0] 3: doSomething()``2.1*: update()`
2. 使用交互架构(框选一个区域,标注`loop``alt`
---
## 💡 五、协作图
### 协作图 vs 顺序图
| 维度 | 顺序图 | 协作图 |
|------|--------|--------|
| **强调** | **时间顺序** | **空间位置关系** |
| **生命线** | 有(从上到下) | 无 |
| **控制焦点** | 有(矩形条) | 无 |
| **消息序号** | 通常简化 | 必须完整标注 |
| **多对象** | 不直观 | 可以表达 |
| **主动对象** | 不直观 | 可以表达 |
🔑 **核心区别**:顺序图强调"什么时间谁调用了谁",协作图强调"谁跟谁有连接关系"。
### 协作图的特殊元素
| 元素 | 说明 |
|------|------|
| **多对象** | 代表一组对象,发给它的消息是发给整个集合 |
| **主动对象** | 拥有自己控制线程的对象,可以主动发起消息 |
| **{new}** | 标记对象在交互中被创建 |
| **{destroy}** | 标记对象在交互中被销毁 |
---
## ✍️ 边学边练(一)
**题目**ATM取款的基本流程如下请画出分析阶段的顺序图。
1. 用户输入取款金额
2. 系统判断账户余额是否足额
3. 若足额,则出钞并修改账户余额
4. 若不足额,则取款失败
**答案:**
顺序图包含对象:`:客户``:ATM界面``:账户`
消息序列:
```
1. 客户 → ATM界面: 输入金额(amount)
2. ATM界面 → 账户: 查询余额()
3. 账户 → ATM界面: 返回余额(balance)
4. ATM界面 → 自己: [balance>=amount]判断
5a. ATM界面 → 账户: 扣款(amount) [金额足够]
5b. ATM界面 → 客户: 显示"余额不足" [金额不足]
```
⚠️ 关键步骤4的判断是ATM界面对象自己的处理用反身消息或不画都可以。
---
## ✍️ 边学边练(二)
**题目**:判断以下场景应该用调用消息还是异步消息。
1. 用户点击"登录"按钮,系统验证用户名密码
2. 用户上传文件后,系统后台写入日志
3. 用户查询订单列表,系统返回查询结果
4. 系统给所有订阅用户发送邮件通知
**答案:**
1. **调用消息(同步)**—— 必须等验证结果,用户才能进入下一步
2. **异步消息**—— 写日志不阻塞用户操作
3. **调用消息(同步)**—— 必须等返回结果才能显示
4. **异步消息**—— 发邮件是批量后台操作,不需要等待
🔑 **判断标准**:发送者是否**必须等待**结果才能继续。必须等=调用消息,不必等=异步消息。
---
## 💡 六、交互建模的步骤
1. 根据一个用例的用例描述,找出**基本事件流**和**可选事件流**
2. 确定参与交互的**对象**(参考类图)
3. 按事件流的**先后次序**确定消息发送次序
4. 标注需要**创建**和**撤销**的对象
5. 处理**循环**和**分支**消息
---
## 📝 章末自测
**1. 填空题**
- 顺序图的四个核心元素是:( ____ )、( ____ )、( ____ )、( ___ _
- 发送后等待返回的消息叫( ____ )消息,发送后继续执行的消息叫( ____ )消息
- 顺序图强调( _____ )顺序,协作图强调( ____ )关系
**2. 判断题**
- ( ) 调用消息的返回消息必须画出来
- ( ) 顺序图可以表示对象的创建和销毁
- ( ) 协作图中消息序号1.1表示它在消息1完成后才开始
**3. 简答题**
- 顺序图和协作图各有什么优势和适用场景?
**答案:**
**填空题**:对象、生命线、控制焦点、消息;调用(同步)、异步;时间、空间位置
**判断题**
- ❌ 调用消息的返回消息可以省略不画(隐式)
- ✅ 对象顶部放置={new},虚线末端×={destroy}
- ❌ 消息1.1在消息1**完成之前**就必须完成(嵌套含义)
**简答题**
- 顺序图:适合展示按时间顺序发生的消息交互,直观易懂,适合分析单个用例的执行流程
- 协作图:适合展示对象之间的静态连接关系,能表达多对象和并发,适合整体架构分析
---
> 🔗 上一篇:[第4章 类图与对象图](第04章-类图与对象图.md) | 下一篇:[第6章 状态图与活动图](第06章-状态图与活动图.md)