UML 的真正价值在于:它并非一套僵化的规范,而是一种用于结构化思考与团队沟通的通用语言。掌握 UML 是软件设计的必备技能,也是高阶开发者的核心能力之一。
1. 类图 class diagram
类图不同于 ER 图——后者用于描述关系型数据库中的实体及其关系,而类图则是面向对象开发的核心工具。一份设计良好的类图,几乎等同于系统的代码骨架。
1.1. 认识类图
接口、类、实现关系、泛化关系、关联关系、依赖关系; 同时可以包含约束、注解 和 包等。
1.1.1 类
类是面向对象系统中组织结构的核心,是对具有相同属性、行为、关系和语义对象的抽象。
包括名称(name)、属性(attribute)和操作(operation)。
1.1.2 接口
接口是一种特殊的类,所有接口在 UML 中都带有 «interface» 构造型。
在 UML 中,接口使用一个带有名称的小圆圈来进行表示,并且可以通过一条Realize(实现关系)线与实现它的类相连接。
1.2 类之间的关系
- 实现关系(realization ;接口实现)
- 泛化关系 (generalization)
- 依赖关系 (dependency)
- 关联关系(association; 特殊的聚合、组合)
1.2.1. 依赖关系
依赖表示一个模型元素(客户方)需要另一个模型元素(供应方)来达到某种目的,供应方的修改会影响客户方的执行结果。 依赖关系暗示着一个客户方如果没有供应方的支持是不完整的。例如,当给一个雇员计算工资的时候,需要使用计算器。UML中,依赖关系用一个从使用者指向提供者的虚箭头表示
提示:依赖关系应从语义层面理解——客户方依赖提供方以实现某项功能,若提供方发生变更,可能影响客户方的行为。
在 Java 中,方法的入参可视为该类对其的依赖。
1.2.2 泛化关系
泛化(继承)关系用来描述类的一般和具体之间的关系——is a kind of。
在 UML 中,使用一条带空心三角箭头的实线表示,箭头指向父类。
1.2.3 关联关系
关联关系是一种结构关系,指出了一个事物的对象与另一个事物的对象之间的连接。
导航性:若A指向B(导航性) 则B为A的成员变量
提示:关联关系中有1对n,也有1对1。如果带有箭头,则表明是一种单方向的。
1.2.4. 聚合(Aggregation)关系和组合关系(Composition)
关联关系有两种非常重要的形式,分别是聚合(Aggregation)关系和组合(Composition)关系。
聚合和组合都是关联关系的一种特殊情况,如何区别他们,则需要从语义的角度去理解
- 组合 composition:缺一不可。如果其中一个不存在,则整体也无法存在。
例如,CPU 和主板是台式主机的核心组成部分,缺一不可。
- 聚合 aggregation: 一个和一群的关系。一个缺少,并不会影响整体。例如大雁和雁群
1.2.5. 实现关系
大多数情况下,实现关系用来规定接口和实现接口的类或者组件之间的关系。
在 UML 中,实现关系的表示形式和泛化关系的表示符号很相似,使用一条带封闭空箭头的虚线来表示。实现关系还有一种省略的表示法:将接口表示为一个小圆圈并和实现它的类之间用一条线相连
提示:在不同的UML工具中,有不同的展现形式。
1.3. 综合的类图实例
- 接口使用 «interface» 进行标注,是对一组对象行为的抽象,不包含具体实现。例如接口飞翔,需要实现其飞的动作行为
- 类:抽象类,需要斜体。类包括:类名称、特性 和操作。
- 实现:大雁实现飞翔
- 依赖关系:如动物依赖氧气,水。 语义表示。
- 泛化(继承),鸟继承动物
- 聚合关系,大雁和雁群的关系。
- 组合关系: 鸟和翅膀
- 关联关系:企鹅和气候
面向对象设计的核心在于分析与抽象,UML 仅是辅助这一过程的可视化工具
2. 用例图(Use Case Diagram)
用例描述了用户如何通过系统实现特定目标。用例图由系统边界、参与者(Actor)和用例(Use Case)三者构成,用于回答三个关键问题:
- 系统是什么?
- 谁在使用系统?
- 用户希望通过系统完成什么?
用例图向用户展示了其捕获的系统、子系统、类或者组件的行为。简单而言,谁使用这个系统能做什么。
2.1. 认识用例图
描述参与者与用例之间通信。可以以不同的视角展现系统的功能性需求。外部用户能够观察到的系统功能、对客户来讲,用例视图是他们业务领域的逻辑化表达;对于开发者,用例图是系统蓝图、开发依据。
2.2. 认识元素
2.2.1. 参与者/执行者(actor)
执行者是系统、子系统或类发生交互作用的外部用户、进程或者其他系统理想化角色。
2.2.2. 用例
用例是一个外部可见的系统内聚功能单元,功能单元由一种被称为主体(subject)的类所提供。用例的目的是在不揭示主体内部结构的情况下定义一个连贯行为。例如:产品维护。产品维护包括增删改查。
2.2.3. 关系
用例图中涉及的关系有:关联、泛化、包含、扩展。
包含:一个用例包含其他用例、并把它作为自身的片段、这被称为包含关系。
扩展:一个用例可以被定义为基用例的增量扩展、这叫做扩展关系。扩展关系箭头指向被扩展的用例。
泛化:一个用例可以被细化分为一个或多个子用例。任何子用例都可以用于其父用例能够应用的场合。
2.3. 案例
简单的购物系统中部分功能用例图。
[购买者会员]、[系统管理员] 可以看做是参与者/执行者。(一个实际用户可以是多个参与者,参与者类似于角色,一个人可以有多个角色一样)
[购买者会员]和【商品查询】用例交互。
【电子产品查询】用例继承【商品查询】,是一种泛化关系。
【商品信息维护】包含了【产品信息修改】用例和【商品查询】用例
对[系统管理员]参与者进行说明
“导出电子产品查询”是对“电子产品查询”的扩展——它在基础用例的特定扩展点插入附加行为,而基础用例本身对此无感知。
若将“导出”视为“查询”流程中不可或缺的一部分,则也可建模为包含(include)关系。两种建模方式各有适用场景,需根据业务语义判断。
用例图的颗粒度一定要有度,防止粒度过细,导致出现滥用。
3. 序列图(Sequence Diagram)
按时间顺序展示对象间的消息交互。强调“谁在什么时候调用了谁”。用途:API调用链分析、分布式事务协调、性能瓶颈定位(如过多远程调用)。实战技巧:在微服务调试中,序列图可清晰展示跨服务调用链,比日志更直观。
3.1. 认识时序图
- 序列图强调消息传递的时间顺序,即对象之间发送与接收消息的先后次序。
- 序列图用来表现用例中的行为顺序,描述了如何一步步完成系统的某项功能
- 序列图揭示了一个特定场景的交互,即系统执行期间发生在某个时间点的对象之间的特定交互
在UML的表示中,序列图将交互关系表示为一个二维图。其中,纵轴是时间轴,时间沿竖线向下延伸。横轴代表了在交互中各独立的对象
3.2. 元素组成
对象、生命线、激活、消息。
3.2.1. 对象
- 序列图中的对象可以是系统的参与者或者任何有效的系统对象。
- 序列图中对象的符号和对象图中对象所用的符号一样——矩形符号。
- 对象及其类的名称带有下划线,二者用冒号隔开,使用“对象名 :类名”的形式。
- 通常,将一个交互的发起者称为主角,将其置于序列图的顶部
3.2.2. 生命线
生命线(Lifeline)是一条垂直的虚线,表示序列图中的对象在一段时间内的存在
- 每个对象的底部中心的位置都带有生命线。
- 生命线是一个时间线,从序列图的顶部一直延伸到底部,所用的时间取决于交互持续的时间。
3.2.3. 激活
- 序列图可以描述对象的激活(Activation),激活是对象操作的执行,它表示一个对象直接地或通过从属操作完成操作的过程。它对执行的持续时间和执行与其调用者之间的控制关系进行建模。
- 简单地说,激活表示该对象被占用以完成某个任务,去激活指的则是对象处于空闲状态、在等待消息。
- 激活在序列图中用一个细长的矩形框表示,矩形框称为激活条或控制期
- 矩形框的顶端与激活时间对齐,而底端与完成时间对齐。即,对象在激活条的顶部被激活,对象在完成自己的工作后被去激活
3.2.4. 消息
- 消息(Messages)是从一个对象(发送者)向另一个或几个其他对象(接收者)发送信号,或由一个对象(发送者或调用者)调用另一个对象(接收者)的操作。
- 消息定义的是对象之间某种形式的通信,它可以激发某个操作、唤起信号或导致目标对象的创建或撤销。
- 消息有三部分组成:发送者、接收者和活动。消息的表示形式为从发送者对象的生命线指向接收者对象生命线的箭头,箭头的类型表示了消息的类型
3.3. 案例
下面将以“教师查看学生成绩”为例,介绍如何去创建系统的序列图
4. 活动图(Activity Diagram)
类似流程图,但支持并行、分支、泳道(Swimlane)。用于描述业务流程或算法逻辑。活动是某件事情正在进行的状态,它既可以是现实生活中正在进行的某一项工作,也可以是软件系统某个类对象的一个操作
用途:审批流设计、复杂业务规则可视化、跨角色协作流程梳理。
4.1. 认识活动图
在 UML 中活动图中的活动既可以是手动执行的任务,也可以是自动执行的任务。用圆角矩形表示。活动强调的是动作,所以圆角矩形中的文字应该是动作。
用户首先提交订单,随后流程分叉:一方面系统自动生成送货单,另一方面用户选择支付方式……)
4.2. 活动图与流程图的区别
活动图描述系统使用的活动、判定点和分支,看起来和流程图没什么两样,并且传统的流程图所能表示的内容,大多数情况下也可以使用活动图表示,但是两者是有区别的,不能将两个概念混淆
流程图着重描述处理过程,它的主要控制结构是顺序、分支和循环,各个处理过程之间有严格的顺序和时间关系
活动图描述的是活动的顺序关系,它着重表现的是系统的行为,而非系统的处理过程
活动图能够表示并发活动的情形,而流程图不能。
活动图是面向对象的,而流程图是面向过程的。
4.3. 为什么要用活动图
- 描述一个操作执行过程中所完成的工作。说明角色、工作流、组织和对象是如何工作的。
- 活动图对用例描述尤其有用,它可建模用例的工作流,显示用例内部和用例之间的路径。它可以说明用例的实例是如何执行动作以及如何改变对象状态。
- 显示如何执行一组相关的动作,以及这些动作如何影响它们周围的对象。
- 活动图对理解业务处理过程十分有用。活动图可以画出工作流用以描述业务,有利于与领域专家进行交流。通过活动图可以明确业务处理操作是如何进行的,以及可能产生的变化。
- 描述复杂过程的算法,在这种情况下使用的活动图和传统的程序流程图的功能是差不多
4.4. 组成活动图的图形元素
- 动作状态(Action State)
- 活动状态(Activity State)
- 动作流(Action Flow)
- 分支(Branch)与合并(Merge)
- 分叉(Fork)与汇合(Join)
- 泳道(Swimlane)
- 对象流(Object Flow)
4.4.1. 动作状态
- 动作状态是指执行原子的、不可中断的动作,并在此动作完成后通过完成转换转向另一个状态。
- 在 UML 中动作状态使用平滑的圆角矩形表示,动作状态所表示的动作写在平滑的圆角矩形内部。
动作状态。语法结构:动宾
4.4.2. 活动状态
- 活动状态用于表达状态机中的非原子的运行。
- 活动状态的表示图标也是平滑的圆角矩形,并可以在图标中给出入口动作和出口动作等信息
4.4.3. 动作流
- 所有动作状态之间的转换流称之为动作流。
- 与状态图的转换相同,活动图的转换也用带箭头的直线表示,箭头的方向指向转入的方向
4.4.4. 分支与合并
- 分支是用菱形表示的,它有一个进入转换(箭头从外指向分支符号),一个或多个出转换(箭头从分支符号指向外)。而每个出转换上都会有一个监护条件,用来表示满足什么条件的时候执行该转换。
- 出转换的条件应当是互斥的,这样可以保证只有一条出转换能够被触发。
合并指的是两个或者多个控制路径在此汇合的情况。合并表示从对应的分支开始的条件行为的结束。
4.4.5. 分叉与汇合
- 分叉和汇合都使用加粗的水平(或者竖直)线段表示
- 分叉用于将动作流分为两个或者多个并发运行的分支,而汇合则用于同步这些并发分支,以达到共同完成一项事务的目的。
注意:分叉与汇合的特性。分叉并行,汇合等待同步
- 分叉可以用来描述并发线程,每个分叉可以有一个输入转换和两个或多个输出转换,每个转换都可以是独立的控制流。
- 汇合代表两个或多个并发控制流同步发生,当所有的控制流都达到汇合点后,控制才能继续往下进行。
- 如果一个处理在其他处理之前到达了 汇合 ,它将会等待,直到所有的处理都准备好之后才会向联结传递控制权。
每个汇合可以有两个或多个输入转换和一个输出转换
4.4.6. 区分合并与汇合
- 合并结合了两个以上的控制路径,在任何执行中每次只走一条,不同路径之间是互斥关系。
- 汇合结合了两条或者两条以上的并行控制路径,在执行过程中,所有路径都要走过,先到的控制流要等其他路径的控制流到达后才能继续运行
4.5. 泳道
- 泳道将活动图中的活动按职责化分为若干组,并把每一组指定给负责这组活动的业务组织
- 在活动图中,泳道用垂直实线绘出,垂直线分隔的区域就是泳道。
- 在泳道上方可以给出泳道的名字,负责泳道内的全部活动。
- 在包含泳道的活动图中,每个活动只能明确地属于一个泳道
- 泳道中,按职责划分为若干个组。属于职责划分,可以分为:客户、系统、供应商。各司其职,互不干涉。例如:系统负责生成送货单和收款
- 分叉和汇合是成对出现的。分叉是并行,汇合时等待。直到所有分支都走完后才往下一个活动。
- 活动图描述的是活动的顺序关系,它着重表现的是系统的行为,而非系统的处理过程
- 分支和合并是只有每次只能走一条,不同路径之间是互斥的。
5. 状态机图(State Machine Diagram)
描述对象在其生命周期内响应事件所经历的状态变迁。用途:订单状态流转(待支付→已支付→已发货→已完成)、设备控制逻辑、游戏AI行为树。深度价值:强制你考虑所有可能的状态和转换条件,避免“状态遗漏”导致的Bug。
5.1. 认识状态机
面向对象分析与设计中,对象的状态、状态的转换、触发状态转换的事件、对象对事件的响应(即事件的行为)等都可以用状态图来描述。
状态图通过建立类对象的生命周期模型来描述对象随时间变化的动态行为
它用于描述某个特定对象在其生命周期中所有可能的状态,以及由于各种事件的发生而引起状态之间的转移和变化
5.2. 状态图组成
状态图由初始状态、终止状态、状态、转换、判定等组成
5.3. 案例
创建一个状态图来描述银行卡从最初制造到顾客使用的各种状态过程
状态图创建步骤:1. 选中建模实体 2. 对各种状态进行建模 3. 找相关事件和转换。 需要在转换的箭头上添加事件行为。
6. 协作图 (UML 2.x 通信图)
文档中 “协作图” 是 UML 1.x 的旧称,UML 2.x 已统一更名为 “通信图”
协作图强调发送和接收消息的对象之间的结构组织的交互图,显示对象、对象之间的链接以及对象之间的消息。
6.1. 认识协作图
协作图就是表现对象协作关系的图,它表示了协作中作为各种类元角色的对象所处的位置,在图中主要显示了类元角色(Classifier Roles)和关联角色(Association Roles)
类元角色和关联角色描述了对象的配置和当一个协作的实例执行时可能出现的连接;当协作被实例化时,对象受限于类元角色,连接受限于关联角色。
6.2. 组成元素
协作图(Collaboration Diagram)是由对象(Object)、消息(Messages)和链(Link)等构成的
6.2.1. 对象
协作图中对象也是类的实例,其表示形式使用包围名称的矩形框来标记、所显示的对象及其类的名称带有下划线、二者用冒号隔开、使用“对象名:类名”的形式等
6.2.2. 消息
- 在协作图中,可以通过一系列的消息(Messages)来描述系统的动态行为。
- 每个消息包括一个顺序号以及消息的名称。为了说明交互过程中消息的时间顺序,需要给消息添加顺序号。
- 顺序号是消息的一个数字前缀,是一个整数,由1开始递增,每个消息都必须由唯一的顺序号。嵌套消息使用点表示法
6.2.3. 链
在协作图中的链是用连接各个对象之间的实线表示。
- 链是关联的实例,当一个类与另一个类之间有关联时,这两个类的实例之间就有链,一个对象就能向另一个对象发送消息。所以链是对象间的发送消息的路径。
- 为了说明一个对象如何与另一个对象连接,可以在链的末路上附上一个路径构造型。如构造型<>,表示指定对象对发送方而言是局部的
6.3. 协作图与序列图的区别与联系
6.3.1. 时序图
取100元人民币的时序图
6.3.2. 协作图
取100元人民币的协作图
- 都是交互图,描述对象之间的交互
- 都包含一系列消息集合
- 时序图强调消息传送的时间先后顺序
- 协作图中描述了该协作所有对象组成的网络结构以及相互发送消息的整体行为
6.4. 案例
协作图强调整体行为,时序图强调时间顺序。
以下以“学生信息管理系统”的一个简单用例“教师查看学生成绩”为例,介绍如何创建系统的协作图。
7. 组件图
用于可视化系统组件的组织和关系。
7.1. 认识组件图
这些图有助于将复杂的系统分解成易于管理的组件,展示它们之间的相互依存关系,确保高效的系统设计和架构。
7.2. 案例
组件图用于展示系统内部各模块(组件)的组织方式及其依赖关系,体现“小模块如何组装成大系统”的架构逻辑
8. 部署图
部署图是一种可视化系统架构的图表,展示软件组件如何部署到硬件上。它能清晰地显示组件在服务器、工作站和设备等不同节点上的分布情况。例如计算机和设备,以及它们之间是如何连接的。部署图的使用者是开发人员、系统集成人员和测试人员。部署图用于表示一组物理结点的集合及结点间的相互关系,从而建立了系统物理层面的模型。
部署图在实际开发中应用广泛。
8.1. 案例
使用 UML 部署图为软件组件的物理部署建模。在部署图中,硬件组件(例如,web服务器、邮件服务器、应用服务器)被呈现为节点,其中在硬件组件内运行的软件组件呈现为工件。
9. 对象图
对象图是一种图形表示法,展示对象及其在特定时刻的关系。它提供了系统结构的快照,捕捉了存在的实例及其关联的静态视图。
对象之间的关系是用以下符号定义的
10. 包图
使用包图管理大型项目的模型。包图也可用于呈现子系统或模块之间的结构和依赖性。
11. 总结
UML 是否过时?
当前开发者更倾向于使用白板、Draw.io 或 Excalidraw 等工具绘制“类 UML 风格”的草图,而非严格遵循 UML 规范。这并非否定 UML 的价值,而是强调沟通效率优先于形式合规。
无需精通所有 UML 图,但应掌握类图、序列图、状态机图、用例图和部署图等 UML 图。
一些参考资料和网站:
www.visual-paradigm.com/tutorials/
《大象 Thinking in UML 》第二版