前置知识: 软件工程与测试

UML 图详解

6 min中级

UML类图、时序图、活动图、状态图等核心图类型详解。

1. 从”建筑施工图”说起

1.1 为什么需要”图”

想象盖一栋大楼。施工队不会靠”口头描述”干活,而是看建筑施工图——每根梁在哪、每堵墙多厚、管线怎么走,都画得清清楚楚。图纸让”想法”变成”可执行的规范”。

UML(Unified Modeling Language,统一建模语言)就是软件的”建筑施工图”:用一套标准化的图形,描述软件的结构(类、对象、组件)和行为(流程、状态、交互),让团队对”系统长什么样、怎么运作”达成一致认知。

1.2 UML 的两种图

UML 定义了 14 种图,分为两大类:

flowchart TD
    T0["UML图"]
    T1["结构图(静态)<br/>系统"长什么样""]
    T2["类图"]
    T3["对象图"]
    T4["组件图"]
    T5["部署图"]
    T6["包图"]
    T7["组合结构图"]
    T8["行为图(动态)<br/>系统"怎么运作""]
    T9["用例图"]
    T10["活动图"]
    T11["状态机图"]
    T12["时序图"]
    T13["通信图"]
    T14["交互概览图"]
    T15["时间图"]
    T0 --> T1
    T0 --> T8
    T1 --> T2
    T1 --> T3
    T1 --> T4
    T1 --> T5
    T1 --> T6
    T1 --> T7
    T8 --> T9
    T8 --> T10
    T8 --> T11
    T8 --> T12
    T8 --> T13
    T8 --> T14
    T8 --> T15

核心认知:不需要掌握全部 14 种。日常开发最常用的只有 5 种:类图(结构)、时序图(交互)、活动图(流程)、状态机图(状态)、用例图(需求)。本篇重点讲这 5 种。

2. 类图:系统的”骨架”

类图是最常用、最重要的 UML 图,描述系统的类、类的属性和方法、以及类之间的关系。它是面向对象设计的”主图”。

2.1 类的表示

classDiagram
    class ClassName {
        -privateAttr: Type
        #protectedAttr: Type
        +publicAttr: Type
        +publicMethod(): Ret
        -privateMethod()
    }

符号含义:

符号可见性
+public(公开)
-private(私有)
#protected(受保护)

2.2 类间关系(重点)

类之间的关系是类图的核心。六种关系按”强度”排列:

关系符号含义示例
依赖- - →A 使用 B(临时使用)方法参数
关联——→A 知道 B(长期引用)成员变量
聚合◇——→A 包含 B(弱拥有,B 可独立存在)部门-员工
组合◆——→A 拥有 B(强拥有,B 随 A 消亡)人-心脏
泛化——▷A 继承 B子类-父类
实现- -▷A 实现 B 接口实现类-接口

关系强度:依赖 < 关联 < 聚合 < 组合 < 泛化/实现

最容易混淆的是聚合 vs 组合:

  • 聚合(弱拥有):部门没了,员工还在(员工属于公司,但可以跳槽)——用空心菱形
  • 组合(强拥有):人没了,心脏也没了(部件不能独立存在)——用实心菱形

判断技巧:问”如果整体消失了,部分还能存在吗?“能 → 聚合;不能 → 组合。

2.3 多重性

标记含义
1恰好一个
0..1零或一个
*任意多个
1..*一个或多个
0..*零或多个

示例:订单类图中,Order 1 ── * OrderItem 表示”一个订单包含多个订单项”。

3. 时序图:系统的”对话记录”

时序图描述对象之间按时间顺序的消息交互——就像一段”对话记录”,看出”谁先调谁、谁等谁、结果如何”。

3.1 基本元素

元素说明
参与者交互的对象
生命线虚线,表示对象存在时间
激活条矩形条,表示对象正在执行
同步消息实心箭头,等待返回
异步消息开放箭头,不等待
返回消息虚线箭头
自调用消息指向自身

3.2 一个登录时序图示例

sequenceDiagram
    participant C as 客户端
    participant S as 服务端
    participant D as 数据库
    C->>S: 提交登录请求
    S->>S: 验证参数
    S->>D: 查询用户
    D-->>S: 返回用户
    alt 密码正确
        S-->>C: 登录成功
    else 密码错误
        S-->>C: 密码错误
    end

3.3 组合片段

时序图可以表达复杂逻辑:

操作符含义
alt条件分支(if-else)
opt可选执行(if)
loop循环
par并行执行
critical临界区
break中断

4. 活动图:系统的”流程图”

活动图描述业务流程或算法逻辑——类似流程图,但更规范。

4.1 基本元素

flowchart TD
    S([起始节点]) --> A1[活动1]
    A1 --> D{决策}
    D --> A2[活动2]
    D --> A3[活动3]
    A2 --> M{合并}
    A3 --> M
    M --> E([终止节点])
元素说明
起始节点实心圆
终止节点实心圆加外圈
活动节点圆角矩形
决策节点菱形
合并节点菱形
分叉/汇合粗横线(并行)
泳道分区表示职责

4.2 泳道活动图

泳道(Swimlane)把活动按”执行者”分区,展示”谁负责哪一步”:

sequenceDiagram
    participant C as 客户端
    participant S as 服务端
    participant D as 数据库
    C->>S: 提交订单
    S->>S: 验证订单
    S->>D: 保存数据
    D-->>S: 返回结果
    S-->>C: 显示确认

泳道的价值:一眼看出”职责分布”——哪里是客户端的活、哪里是服务端的活、哪里是数据库的活。这对接口设计(谁该提供什么)很有帮助。

5. 状态机图:系统的”状态变化”

状态机图描述对象的状态变化——特别适合订单、审批、流程类系统。

5.1 基本元素

stateDiagram-v2
    [*] --> 待下单
    待下单 --> 待支付: 下单
    待支付 --> 已支付: 支付
    待支付 --> 已取消: 取消订单
    已支付 --> 已发货: 发货
    已发货 --> 已完成: 确认收货

5.2 状态转换表

状态机图也可以用表格表达(状态转换表),两者等价:

当前状态事件动作目标状态
待下单下单创建订单待支付
待支付支付处理支付已支付
待支付取消释放库存已取消
已支付发货更新物流已发货
已发货确认收货完成订单已完成

状态机图的实战价值:开发前画好状态图,能提前发现”非法状态转换”(如”已取消 → 已发货”就不应该存在),避免上线后出 bug。

6. 其他常用 UML 图

6.1 组件图

展示系统的组件及其依赖关系(架构层面):

flowchart TD
    W[Web前端] --> G[API网关]
    G --> U[用户服务]
    G --> O[订单服务]
    G --> P[支付服务]

6.2 部署图

展示硬件节点和软件部署(运维层面):

flowchart TD
    W[Web服务器<br/>Nginx] --> A[应用服务器<br/>Node.js]
    A --> D[数据库服务器<br/>MySQL]

6.3 用例图

展示”谁(参与者)能用系统做什么(用例)“(需求层面,见《需求分析方法》):

7. 实践建议:怎么用好 UML

UML 不是”画得越全越好”,而是”在合适的时候画合适的图”:

场景推荐图
需求讨论用例图、活动图
设计阶段类图、时序图
状态复杂系统状态机图
架构评审组件图、部署图

工具推荐:

  • Mermaid(本文档所用):Markdown 内嵌,版本可控(文档即代码)
  • PlantUML:文本描述 UML,自动生成图
  • draw.io / StarUML:可视化拖拽

核心原则:图的价值在于沟通,不在于美观。一张”画得很丑但大家看懂了的图”,远胜”画得很漂亮但没人看得懂的图”。

8. 常见误区

误区一:要把 14 种 UML 图全部掌握。 → 日常开发 5 种够用(类图、时序图、活动图、状态机图、用例图),其余用到再学。

误区二:UML 图是”画完就扔”的文档。 → 图是”活文档”,要随代码一起维护(文档即代码)。过期的图比没有更糟。

误区三:聚合和组合分不清没关系。 → 这是类图最常见的考点和实战点。记住”整体消失,部分还能存在吗”——能是聚合,不能是组合。

误区四:UML 是”设计阶段”的专属。 → UML 可以用于任意阶段的沟通——需求讨论(用例图)、代码走读(类图)、故障排查(时序图)。