📄 一句话概括
职责表可以直接摊成时序——实测 5 个动作落到 3 个类、重叠 0 处,图是手段,那张归属表才是成果。
📝 本节和前面几节的关系
8.8 用类图理顺了【谁包含谁】,这一节理顺【谁负责什么】。两件事合起来,第 10 章才有地基。
一、从职责表到时序
职责表长这样:一个动作一列,后面写归属的类。 摊成时序:挑一条主线,把每一步变成一条消息,箭头两边就是【谁交给谁】。 判定标准只有一条:每个动作恰好一个归属,两个类都能做就是重叠。
二、实测:5 动作 3 类 0 重叠
借书、还书、算逾期 → Loan;算罚款 → Fine;收款 → Cashier。
5 个动作、3 个类、重叠 0 处。
一个类领 3 个动作不算问题——那叫聚合,只要动作之间是同一个职责就行。
三、时序图与通信图的分工
时序图回答【按什么顺序找谁】:先验证身份,再查库存,再登记。 通信图回答【谁跟谁直接连】:连线越多,这两个类的耦合越紧。 实践中先画时序再折通信,因为顺序比连线好想。
四、图是手段,表是成果
评审时真正被确认的是那张归属表,不是图上箭头的弯曲程度。 所以别在美化上花时间——图上多一个圆角,不会让职责更清楚。 第 10 章讲拟人化和职责分配时,用的就是这张表加这两张图。
五、动手 Demo:表示职责分配的时序图和通信图
先列职责表,允许一个动作挂在多个类上(用来验证重叠)。 再把一条主线排成时序图,数消息与连线。
duty = {"借书": "Loan", "还书": "Loan", "算逾期": "Loan",
"算罚款": "Fine", "收款": "Cashier"}
owner = {}
for act, cls in duty.items():
owner.setdefault(cls, []).append(act)
seq = [("Reader", "Loan", "借书"), ("Loan", "Fine", "算罚款"),
("Loan", "Cashier", "收款"), ("Cashier", "Reader", "出单")]
print(len(duty), len(owner), len(seq), len(set((a, b) for a, b, r in seq)))
# 5 3 4 4
实跑输出:
--------------------------------------------------------------------
表示职责分配的时序图和通信图
--------------------------------------------------------------------
职责表(谁负责什么)可以直接摊成时序——**一条主线串起所有归属**。实测:
序号 从 到 职责
----------------------------------------
1 Reader Loan 借书
2 Loan Fine 算罚款
3 Loan Cashier 收款
4 Cashier Reader 出单
动作总数 5 个
承接的类 3 个
Cashier 负责 收款
Fine 负责 算罚款
Loan 负责 借书/还书/算逾期
动作归属重叠 0 处(每个动作恰好一个类)
时序消息 4 条,用时序图看先后
通信连线 4 条,用通信图看耦合
**实测:5 个动作全部有唯一归属,重叠 0 处。**
**时序图回答【按什么顺序找谁】,通信图回答【谁跟谁直接连】。**
**第 10 章讲职责分配时用的就是这两张图**——图是手段,表才是成果。
实测:5 个动作、3 个类、0 处重叠;时序 4 条消息、通信 4 条连线。
Loan 领 3 个动作是聚合,不是错——只要它们属于同一个职责。
看这张表就能审设计:任何一行有两个类,就是没分清的职责。
30 秒实验
- 列出你系统里的 6 个业务动作,逐个写归属类,找找有没有两个类都能做的。
- 把一条主线的时序画出来,数一数哪个对象收到的消息最多。
常见误区
- 以为一个类领多个动作就是设计错误。聚合正常,重叠才是问题。
- 以为图画得漂亮就等于设计好。被确认的是归属表,不是箭头。
自测三问(点开对答案)
1. 职责分配的硬规矩是什么? —— 每个动作恰好一个归属;两个类都能做就是职责重叠。 2. 实测分布如何? —— 5 个动作、3 个类、0 处重叠;Loan 领 3 个属聚合。 3. 两张图各自回答什么? —— 时序图回答按什么顺序找谁,通信图回答谁跟谁直接连。- ☐ 8.10 UML的使用方法之三:表示非面向对象的信息
相关笔记
- 使用类图表示根据集合论进行整理的结果 — 上一半(包含关系)
- 为何化为了通用的归纳整理法 — 职责表的业务来源
- 使用时序图和通信图表示动作 — 同一套图用在代码上
- 🧩 面向对象是怎样工作的 · 索引