UML 类图与时序图:面向对象设计表达
FreeGuideOnline
最新
2026-07-01
UML 类图与时序图:面向对象设计表达
什么是UML
统一建模语言(UML)是一种标准化的可视化建模语言,用于在软件开发过程中对系统进行规约、可视化、构造和文档化。它帮助团队在编码之前理解、设计复杂系统的结构和行为。本教程聚焦于两种最常用的UML图:类图用于表达静态结构,时序图用于展示动态交互。
第一部分:类图——系统的静态蓝图
类图是面向对象系统的核心建模工具,它描述了系统中类的集合、类的内部结构以及类之间的各种关系。它不关心时间或流程,而是回答“有哪些部分”和“它们之间如何关联”的问题。
类的表示法
在UML中,一个类用一个被分为三层的矩形表示:
- 顶层:类名(正体,抽象类用斜体)。
- 中间层:属性列表。
- 底层:方法(操作)列表。
+----------------------------+
| ClassName |
+----------------------------+
| - attribute1 : DataType |
| - attribute2 : DataType |
+----------------------------+
| + method1() : ReturnType |
| + method2(param : Type) |
+----------------------------+
可见性修饰符:
+公开 (public)-私有 (private)#受保护 (protected)~包内可见 (package)
属性完整语法:
可见性 名称 : 类型 [多重性] = 默认值 {约束}
示例:- balance : double = 0.0 {non-negative}
方法完整语法:
可见性 名称(参数列表) : 返回类型
示例:+ withdraw(amount : double) : bool
核心关系类型:从弱到强
理解关系是读懂类图的关键。下表涵盖了所有基础关系:
| 关系类型 | 符号风格 | 箭头含义 | 代码体现 | 说明 |
|---|---|---|---|---|
| 依赖 | 带箭头的虚线 ----> |
使用者指向被使用者 | 局部变量、方法参数 | 一种暂时的、最弱的 “使用” 关系。类A的变化可能影响类B。 |
| 关联 | 实线 —— 或带箭头实线 ——> |
导航方向 | 成员变量 | 一种稳定的结构关系。类A持有对类B的引用。可标注多重性。 |
| 聚合 | 空心菱形加实线 ◇—— |
整体指向部分 | 成员变量(可共享) | 弱 “拥有” 关系,部分可以脱离整体独立存在。如:球队与球员。 |
| 组合 | 实心菱形加实线 ◆—— |
整体指向部分 | 成员变量(不可共享) | 强 “拥有” 关系,部分的生命周期由整体控制。如:订单与订单行目。 |
| 实现 | 带三角的虚线 ----▷ |
实现者指向接口 | implements 关键字 |
类实现接口中的抽象方法。 |
| 泛化 | 带三角的实线 ——▷ |
子类指向父类 | extends 关键字 |
继承,代表 “是一种” 的关系。抽象类和抽象方法用斜体。 |
多重性标注:在关联关系的两端标注数字或范围,表示“多少个”。
1严格1个0..10或1个*或0..*0到多个1..*至少1个- 示例:
Customer 1 —— * Order表示一个客户有多个订单,一个订单只属于一个客户。
类图实例解读
下面是一个简化的电商订单域类图:
+------------------+ +-------------------+
| Customer | | Order |
+------------------+ +-------------------+
| - id : String | 1 * | - orderId : String |
| - name : String |◇──────────────▶| - date : Date |
+------------------+ +-------------------+
|
| 1
|
| ◆ 组合(强拥有)
|
1..*
+-------------------+
| OrderItem |
+-------------------+
| - quantity : int |
+-------------------+
| + getSubTotal() |
+-------------------+
- Customer与Order是一对多关联,且为聚合(空心菱形),因为订单保留客户信息,但客户删除时订单可能仍然存在。
- Order与OrderItem是组合,项的生命周期完全依赖订单,订单取消则行目消失。
- 多重性表示每个订单至少包含一个订单行目。
第二部分:时序图——捕捉对象间的对话
时序图诠释了特定场景下对象之间消息传递的时间顺序。它垂直向下表示时间流逝,水平方向排列参与者,重点在于“谁在什么时间对谁说了什么”。
基本构件
- 生命线:从每个对象图标向下延伸的虚线,表示对象存在的时间段。
- 激活条:生命线上的细长矩形,表示对象正在执行操作、处于活动状态的时间。
- 消息:带箭头的水平线,从一个生命线指向另一个。类型包含:
- 同步消息:实线实心箭头
—▶,调用者等待返回。 - 返回消息:虚线开箭头
--▷,一般表示同步调用的返回。 - 异步消息:实线开箭头
—▷,发送后不等待,继续执行。 - 自调用消息:箭头指向自己,表示对象内部方法调用。
- 创建消息:虚线开箭头指向新创建对象的生命线头部,配上
<<create>>构造型。
- 同步消息:实线实心箭头
- 片段与组合:用矩形框住一组交互,标签如
alt(条件分支)、loop(循环)、opt(可选)、par(并行)等,能够表达复杂控制流。
建模顺序:从左到右,从上到下
- 确定场景上下文(例如“用户成功支付订单”)。
- 绘制参与对象:从左到右放置,通常将发起者放在最左,重要处理器放中间,外部系统放右侧。
- 用消息线逐条绘制交互,并在激活条上标明执行期。
- 利用组合片段表达条件逻辑和循环。
时序图实例:电商订单支付流程
以下示例展示一个包含条件判断的支付场景。
用户 订单服务 支付网关 库存服务
│ │ │ │
│ placeOrder() │ │ │
├──────────────▶│ │ │
│ │ 激活 │ │
│ ├─────────────┐ │ │
│ │ 校验订单 │ │ │
│ │◄────────────┘ │ │
│ │ │ │
│ │ processPayment(amount) │
│ ├──────────────▶│ │
│ │ │ 激活 │
│ │ ├─────────────┐ │
│ │ │ 授权交易 │ │
│ │ │◄────────────┘ │
│ │ │ │
│ │ alt [授权成功] │
│ │ │ │
│ │ paymentSuccess() │
│ │◄──────────────│ │
│ │ │ │
│ │ updateInventory(itemId, qty) │
│ ├──────────────────────────────▶│
│ │ │ │ 激活
│ │ │ ├────┐
│ │ │ │扣减│
│ │ │ │◄───┘
│ │ invOK() │ │
│ │◄──────────────────────────────│
│ │ │ │
│ │ [授权失败] │
│ │ paymentFailed(reason) │
│ │◄──────────────│ │
│ │ │ │
│ │ end │ │
│ │ │ │
│ orderResult │ │ │
│◄──────────────│ │ │
│ │ │ │
解读:
- 用户调用订单服务的
placeOrder(),触发内部校验。 - 订单服务向支付网关发送同步消息
processPayment,并等待返回。 - 片段
alt根据支付结果分为两个路径:成功时调用库存服务扣减,失败时仅返回失败原因。 - 所有返回用虚线箭头表示,最后订单服务将结果返回给用户。
实践准则与常见误区
类图
- 牢记目的:它是结构蓝图,不是实现图。不要在类图中画流程。
- 关系不要混用:除非有“部分-整体”特征且部分不能独立存在,否则不要轻易使用组合。大多数情况用关联或聚合。
- 属性 vs 关联:如果某个概念自身有丰富属性和行为,应作为类并用关联连接;如果只是基本类型(String、int),作为属性即可。
时序图
- 聚焦关键路径:一张时序图只描绘一个清晰场景,不要试图把所有异常分支揉进一张图。
- 避免过度详细:只表达核心对象间的协作,底层工具类或 trivial 的 getter/setter 通常不画。
- 合理使用片段:
alt、loop虽可表达逻辑,但不要让时序图变成程序流程图。坚持“主要成功路径”优先原则。
工具推荐
- 免费在线工具:PlantUML (文本驱动)、draw.io、Lucidchart
- 集成开发环境插件:IntelliJ IDEA Ultimate 自带 UML 生成,VS Code 有 PlantUML 插件
结语
掌握类图和时序图,你就能清晰地表达面向对象设计的静态骨架和动态协作。从简单的小模块开始练习,逐渐过渡到完整的系统模块,你会发现UML成为沟通设计、降低复杂度的有力助手。