UML 简介
统一建模语言(UML)是业界标准,用于绘制可视化类层次结构、子系统交互、时序图等图表。本书在类图中使用 UML。完整讲解整个 UML 标准本身就足以写成一本书,因此本附录仅对本书中使用到的那些方面做简要介绍。UML 标准有不同版本,本书使用的是 UML 2。
UML 定义了以下类型的图表:
- 结构型 UML 图
- 类图
- 对象图
- 包图
- 组合结构图
- 组件图
- 部署图
- Profile 图
- 行为型 UML 图
- 用例图
- 活动图
- 状态机图
- 交互图
- 时序图
- 通信图
- 时间图
- 交互概览图
由于本书只使用类图和时序图,因此本附录只进一步讨论这两种图。
类图用于可视化单个类,并且可以包含数据成员和成员函数。它们也用于展示不同类之间的关系。
在 UML 中,类表示为一个最多包含三个分区的方框,内容如下:
- 类名
- 数据成员
- 成员函数
图 D.1 展示了一个示例。MyClass 有两个数据成员——一个类型为 string,另一个类型为 float——并且它有两个成员函数。每个成员前面的加号和减号表示其可见性。下表列出了最常用的可见性:

[^FIGURE D.1]
| VISIBILITY | MEANING |
|---|---|
| + | 公有成员 |
| - | 私有成员 |
| # | 受保护成员 |
根据类图的目标,有时会省略成员细节,此时类会表示为一个方框,如图 D.2所示。例如,如果你只关心不同类之间关系的可视化,就可以采用这种方式。

[^FIGURE D.2]
UML 2 支持六种类之间的关系:继承、实现、聚合、组合、关联和依赖。下面的小节将介绍这些关系。
继承用一条从派生类指向基类的线来表示。该线在基类一侧以空心三角形结束,用于表示 is-a 关系。图 D.3 展示了一个示例。

[^FIGURE D.3]
实现某个接口的类本质上是在继承该接口(is-a 关系)。不过,为了区分一般继承和接口实现,后者的表示方式与继承相似,但使用虚线而不是实线,如图 D.4所示。ListBox 类派生自 UIElement,并实现了 IClickable 和 IScrollable 接口。

[^FIGURE D.4]
聚合表示 has-a 关系。它用一条线来表示,并在包含另一个类实例或多个实例的类一侧使用空心菱形。在聚合关系中,你还可以选择指定关系中各参与者的多重性。多重性的放置位置,也就是应写在线的哪一侧,起初可能会让人感到困惑。例如,在图 D.5中,一个 Class 可以包含/聚合一个或多个 Student,而每个 Student 可以参加零个或多个 Class。聚合关系意味着,被聚合的对象在聚合者被销毁后仍然可以继续存在。例如,如果一个 Class 被销毁,其 Student 并不会被销毁。

[^FIGURE D.5]
下表列出了一些可能的多重性示例:
| MULTIPLICITY | MEANING |
|---|---|
| N | 恰好 N 个实例 |
| 0..1 | 零个或一个实例 |
| 0..* | 零个或多个实例 |
| N..* | N 个或更多实例 |
组合与聚合类似,视觉表示方式也几乎相同,不同之处在于它使用实心菱形而不是空心菱形。与聚合不同,在组合关系中,如果包含其他类实例的类被销毁,那么这些被包含的实例也会随之销毁。图 D.6 展示了一个示例。一个 Window 可以包含零个或多个 Button,并且每个 Button 必须恰好被一个 Window 包含。如果 Window 被销毁,它所包含的所有 Button 也会被销毁。

[^FIGURE D.6]
关联是聚合的一种泛化。它表示类之间的二元链接,而聚合是单向链接。二元链接可以沿两个方向遍历。图 D.7 展示了一个示例。每本 Book 都知道它的作者是谁,而每位 Author 都知道她写过哪些书。

[^FIGURE D.7]
依赖表示一个类依赖于另一个类。它表示为一条虚线,带有一个指向被依赖类的箭头。通常,虚线上会有一些文字来描述这种依赖关系。回到第 33 章“应用设计模式”中的汽车工厂示例,CarFactory 依赖于 Car,因为工厂会创建汽车。这一点在图 D.8中进行了可视化表示。

[^FIGURE D.8]
UML 2 支持四种交互图:时序图、通信图、时间图和交互概览图。本书只使用时序图,下面将对此做简要讨论。
时序图以图形方式表示不同对象之间发送了哪些消息,以及这些消息发送的顺序。时序图由以下组成部分构成:
- 对象: 参与交互的对象实例。
- 生命线: 以图形方式表示对象的生命周期。
- 消息: 消息从一个对象发送到另一个对象。
- 回复: 当一个对象接收到另一个对象发来的消息时,它会发送一个回复。
- 自消息: 对象发送给自己的消息。
- 备选: 表示替代流程,类似于
if-then-else语句中的分支。
图 D.9 展示了一个时序图示例。这是第 4 章“设计专业级 C++ 程序”中的图的简化版本,不过这次图中添加了标签,用于说明图中重要部分的含义。

[^FIGURE D.9]