---
title: UML概念速查
date: 2021-04-04 23:28:22
tags: [架构知识, UML, 组件图, 类图, 对象图, 结构图, 用例图, 活动图, 状态图, 序列图]
categories:
  - [架构知识, UML]
---
UML图是进行软件架构设计时使用的一套标准工具集，通过UML图的绘制和表述，可以清晰明确的表现软件的静态逻辑结构、物理结构以及动态的运行过程等。UML图很简单，并不难理解，但是组成UML图形的图例却十分的丰富，只有完全了解了各种图例所代表的含义，才能顺利读懂UML图所要表达的意思。
<!--more-->

## 概览

UML图主要由以下这些图组成，不同的图会被应用于软件架构设计的不同时期。

```plantuml
@startwbs
* 图
** 结构图
***< 类图
***> 组件图
***< 对象图
***> 扩展机制图
***< 组合结构图
***> 部署图
***< 包图
** 行为图
***< 用例图
***> 活动图
***< 状态图
***> 交互图
****< 序列图
****> 通信图
****< 交互概述图
****> 时间图
@endwbs
```

| 工作阶段 | 工作焦点 | 采用图形 |
|------|--------------|------------------------------------------|
| 业务建模 | 组织系统之间的关系和流程 | 用例图、类图、序列图、活动图 |
| 需求 | 系统边界 | 用例图、序列图、状态图、活动图 |
| 分析 | 系统内的核心域 | 类图、序列图、状态图、活动图、通信图、包图 |
| 设计 | 系统内各域之间 | 类图、序列图、状态图、活动图、通信图、组件图、部署图、时间图、组合结构图、包图 |

## 类图

类图是描述类、类的特性以及类之间关系的图。

### 图例

#### 类

使用分为三个部分的矩形表示，第一部分为类名和类属性，第二部分为类内的属性（字段），第三部分为类内的方法。

对于类内属性和方法的访问性，用以下符号表示：`+`表示public，`-`表示private，`#`表示protected，`~`表示package private。静态属性和方法使用下划线标识，抽象方法使用斜体标识。

属性一般采用`标识名: 类型`的格式书写，方法一般采用`方法名(参数类型列表): 返回类型`的格式书写。

```plantuml
class Class {
    + teacher: Teacher
    + students: List<Student>
    + dismiss(): void
}
```

接口和抽象类、枚举类都是特殊的类，只是类属性标识不同，图示与结构均相同。

#### 包

包对应Java中的`package`，其中会拥有多个类或者接口等。包使用类似于文件夹形式的图形表示。

```plantuml
package School {
    class Teacher
    class Student
    class ClassRoom
}
```

### 类间关系

#### 双向关联

双方知道对方的存在，可以调用对方的公共属性和方法，表现为拥有对方的指针、引用或者实例。使用实直线连接，或者使用带有双向箭头的实直线连接。

```plantuml
class A
class B

A - B
```

```plantuml
class A
class B

A <-> B
```

#### 单向关联

类单方知晓对方的公共属性和方法，表现为拥有对方的指针、引用或实例。使用实线箭头连接，箭头指向被知晓方。

```plantuml
class A
class B

A -> B
```

#### 自关联

类在内部拥有一个自身的指针、引用或者实例。使用实线箭头连接，箭头指向自己。

```plantuml
class A {
    + a: A
}

A -> A
```

#### 聚合

表示类之间的整体与部分的关系，组成整体的组件可独立存在（在特定领域内独立时有意义）时，关系为聚合。使用空心菱形加实直线（或者单箭头实直线）连接两个类，空心菱形指向整体。

```plantuml
class A {
    + b: B
}
class B

A o- B
```

使用带箭头的实直线表示单向聚合。

```plantuml
class A {
    + b: B
}
class B

A o-> B
```

#### 组合

表示整体与部分的关系，组成整体的组件不能独立存在（在特定领域内独立无意义）、且整体与部分之间的生命周期相同时，关系为组合。使用实心菱形加实直线连接两个类，实心菱形指向整体。

```plantuml
class A {
    + b: B
}
class B

A *- B
```

使用带箭头的实直线表示单向组合。

```plantuml
class A {
    + b: B
}
class B

A *-> B
```

#### 依赖

一个类执行功能时，必须要有被依赖类的功能协助，则两个类产生依赖关系。实际使用中，依赖都是单向的，不应该产生双向依赖。使用单箭头虚直线连接两个类，箭头指向被依赖类。

```plantuml
class A
class B

A .> B
```

#### 继承

当两个类存在继承（泛化）关系。使用空心箭头实直线连接两个类，箭头指向被继承的类（父类）。

```plantuml
class Animal
class Tiger

Tiger -|> Animal
```

#### 实现

当一个类实现了一个接口时，关系为实现。使用空心箭头虚直线连接两个类，箭头指向接口。

```plantuml
interface Person
class Student

Student .|> Person
```

#### 嵌套

当一个类中包含另一个类或者接口等时，两个类形成嵌套关系。使用内嵌加号的圆形搭配实直线连接两个类，圆形指向被嵌套类。

```plantuml
class A
class NestedB

A -+ NestedB
```

## 数据库实体图

数据库实体图用来描述数据库表之间的关系，可以用来对数据库表结构以及数据表之间的关联关系进行设计。

### 图例

数据表又称为Entity（实体），表示形状与类图中的类基本一致，也是将一个矩形分为三个部分，第一部分书写数据表或者实体的名称，第二部分书写主键字段，第三部分书写其余字段。所有的非空字段需要在字段名前使用点标记。字段的类型放置在字段名后，与字段名使用冒号隔开。

```plantuml
entity Person {
    * id: varchar(20)
    --
    * name: varchar(50)
    * birthday: datetime
    salary: numeric(10,2)
}
```

### 实体间关系

数据库实体之间主要存在的关系是一对一、一对多、多对一、多对多几种，配合单向关联和双向关联，可以形成多种数据库实体间的关联关系。在数据库实体图中主要通过不同的连接线样式来体现。

以下通过几个常见的关系来简单说明实体间关系图示的绘制方法。

#### 单向一对一关系

```plantuml
entity A
entity B

A -|| B
```

上图表示实体A必定存在一个对应的实体B。连接线上实体B一端的符号表示必定存在一个且仅一个实体，可以使用“11”来助记。

```plantuml
entity A
entity B

A -o| B
```

上图表示实体A可能存在一个对应的实体B。连接线上实体B一端的符号表示存在零个或者一个实体，即最多一个实体，可以使用“01”来助记。

#### 单向一对多关系

```plantuml
entity A
entity B

A -|{ B
```

上图表示实体A中存在最少一个对应的实体B。连接线上实体B一端的符号表示存在一个或者多个实体，即最少一个实体，可以使用“1<”来助记。

```plantuml
entity A
entity B

A -o{ B
```

上图表示实体A中可能存在对应的实体B。连接线上实体B一端的符号表示存在零个或者多个实体，即最少零个、多则不限的实体，可以使用“0<”来助记。

#### 双向对应关系

之前的所有示例中都是单向对应关系，均表示在实体A中包含实体B，或者称为从实体A中访问实体B。双向对应关系则是增加了从实体B中访问实体A的关系，其表示符号和方法与单向关系相同，只是在连接线的实体A一端也增加相应的标记即可。

```plantuml
entity A
entity B

A ||-o{ B
```

例如这个示例中表示实体A中会对应零个或者多个实体B，但是每个实体B必定仅有唯一对应的实体A。

## 用例图

用例图用来描述用户与系统功能单元之间的需求关系，用来展示外部用户所看到的系统功能模型。

### 图例

#### 参与者

通常表示与系统进行交互的用户、组织、外部系统或设备等。用小人来表示。

#### 用例

用例表示外部可见的系统功能或服务，用椭圆表示。

#### 容器

通常代表一个系统，用矩形表示。

#### 关系

用例图中的关系通常包括关联、泛化、包含和扩展，与类图中的表示方法相同。

### 示例

```plantuml
actor Customer as cus
actor Manager as man

rectangle Store {
    man -- (Deliver)
    cus -- (Order)
    (Order) ..> (Database)
    (Deliver) ..> (Database)
}
```

## 活动图

活动图一般用来描述用例图中用例的活动与活动间的约束关系，强调对象间的控制流程。主要用来对业务过程和工作流进行建模，以及用来实现用例。

活动图着重表现一个活动到另一个活动的控制流，流的前进来自内部驱动。与流程图相比，活动图面向对象，主要表现系统行为，而流程图是面向过程的，强调处理顺序和时间关系。

### 图例

#### 起始与终止节点

起始节点使用实心圆表示，每张活动图只能有一个起始节点。终止节点使用包含一个同心实心圆的圆表示，每张活动图可以有多个终止节点。

#### 活动节点

活动使用圆角矩形表示，活动内容书写在矩形内部。

#### 转换

活动间的转换使用实线单箭头连接。

#### 分支条件

分支使用菱形表示，包含一个进入转换和多个离开转换，条件标记在转换上。

#### 并发

并发操作包含分叉（fork）和汇合（join）两个操作节点，分别使用两条粗实线表示。进入分叉节点表示所有分支开始并行运行，共同完成一项事务，全部分支都运行到汇合节点之后，活动才能继续向下执行。

#### 泳道

泳道表示活动转移到了其他的模块或者组件中执行了，通常用来表现组件协作。

### 示例

```plantuml
|Order|
start
|User|
:Check login;
if (Logged in) then (yes)
else (no)
    stop
endif
|Order|
:Add Goods;
:Calculate;
|Finance|
:Accounting;
|Order|
:Generate;
|Database|
:Persist;
stop
```

## 状态图

状态图一般用来描述一个对象的所有状态以及状态之间的转换，一般对应状态机模式。

状态图着重于描述一个对象内的状态转换，驱动力来自于对象外部。

### 图例

状态图所采用的图例与互动图基本一致。不同点在于对于状态的描述。

#### 状态

状态使用圆角矩形表示，在矩形中间使用文字描述状态的名称。状态之内可以继续定义更加详细的状态。

### 示例

```plantuml
[*] --> Neutral
Neutral --> LoginAttempt : Input
LoginAttempt --> LoginFail : No User
LoginAttempt --> LoginFail : Password error
LoginAttempt --> LoggedIn : Success
LoggedIn -> Neutral : Log out
LoginFail --> Neutral : Reset
```

## 序列图

序列图用于进行逻辑建模，描述整个处理过程的基本逻辑。序列图描述了参与过程的各个模块角色之间相互作用以及消息传递关系。

序列图由对象、生命线、激活、消息、分支等元素组成。以下通过一个示例来说明序列图的形式。

```plantuml
actor Administrator as root
actor Operator as main
participant Business as plat
participant Alliance as ally

main -> plat : Query orders
plat -> main : Orders

group Delivery
ally -> plat : Delivery notice
plat -> main : Delivery notice
end

main -> plat : Process delivery
plat -> main : Request conform delivery
activate plat
main -> plat : Confirm delivery
plat -> main : Request authenticate
main -> plat : Authenticate
plat -> root : Request secondary authenticate
root -> plat : Authenticate
deactivate plat

plat -> plat : Notice delivery
plat -> ally : Notice alliance delivery
```

## 组件图

组件图是用来描述组件与组件之间关系的，通常在宏观层面上表现系统某个方面的实现结构。参与组件图表现的，一般都是系统中的物理组件，包括库、程序包、文件等。

### 图例

组件图的图例比较简单，主要有以下几种。

* 组件，使用矩形表示，其中书写组件的名称。
* 接口，组件对外提供或者依赖与外部的操作集合。
    * 提供接口，组件为其他组件提供服务的操作的集合，使用空心圆表示，接口名称放置于图形旁边。
    * 需求接口，组件向其他组件请求服务时所遵循的接口，使用半圆弧表示，通常与其他组件的提供接口对接。
* 端口，被封装的组件的对外窗口，所有出入组件的交互都要通过端口。绘制在组件的边界上，以空心矩形表示。
* 关系，组件与接口之间通过连线来表示关系。
    * 实现关系，组件与接口之间采用实线连接。
    * 依赖关系，组件与其他组件接口之间采用单箭头虚线连接，箭头指向接口。

### 示例

```plantuml
() "Withdraw" as wd
() "Transfer" as tf

[Account] - wd
tf - [Account]
[B2B] ..> tf
wd <.. [ATM]
```

## 对象图

对象图表示一组对象及其之间的关系，是系统某一时刻的详细状态快照，通常用来结合类图来表示一个复杂的实例。

对象图的构建与类图相似，但主要列出属性的具体值。对象间的关联关系基本与类图一致。

### 示例

```plantuml
object Ming {
    name = "Ming"
    age = 12
}

object Mei {
    name = "Mei"
    age = 11
}

Ming - Mei : friend
```
