💡 注意: 所有图表均以PlantUML格式提供。您可以使用Visual Paradigm 图表即代码.
🔹 UML简介
什么是UML?
“统一建模语言(UML)是一种通用的可视化建模语言,用于指定、可视化、构建和记录软件系统的制品。”—— Rumbaugh 等人,1999年
主要特征:
-
🎨 可视化符号: 用于建模系统的图形语法
-
📐 标准化: 自1997年以来由OMG采纳的标准
-
🔧 语言,而非方法: 定义符号,而非流程
-
🌐 应用范围广泛: 可建模业务流程、系统功能、代码结构和数据库模式
UML并非什么
| 误解 | 事实 |
|---|---|
| 一种开发方法论 | 仅仅是一种建模符号 |
| 一种编程语言 | 抽象规范语言 |
| 仅用于面向对象编程 | 适用于数据库、业务建模等 |
| 在各个方面都精确定义 | 早期版本中仍存在一些语义模糊性 |
🔹 历史与标准化
演进时间线

1965-1970:Simula-67(第一种面向对象语言)
↓
1970年代-1980年代:施乐帕克研究中心的Smalltalk
↓
1984:本斯特拉斯特鲁普推出C++
↓
1988-1992:面向对象方法的泛滥(Booch、OMT、OOSE等)
↓
1994:伦巴ugh加入博奇在Rational公司 → 统一工作开始
↓
1995:UML 0.8草案发布
↓
1996:OMG发布标准建模语言的征求建议书
↓
1997:OMG采纳UML 1.1(11月14日)
↓
2000:UML 1.3正式发布
↓
2003:UML 1.5发布;UML 2.0超结构被接受
为什么UML赢得了“方法之战”
-
将50多种竞争性的面向对象方法整合为一种标准
-
得到主要行业巨头(IBM、微软、甲骨文、惠普)的支持
-
提供了可扩展机制以支持定制
-
成为面向对象建模的事实标准
⚠️ 批判性视角:有人认为UML是“由委员会设计的怪物语言”,早期版本语义不精确。
🔹 类与属性
类结构
UML中的类以最多包含三个部分的矩形表示。

@startuml
class Student {
firstName: String
lastName: String
email[0..1]: String
encryptedPW: String
+ totalPoints(): Integer
+ setPassword(pw: String)
+ checkPW(pw: String): Boolean
}
@enduml
属性声明语法
[可见性] 名称[多重性]: 类型 [= 默认值] {属性}
PlantUML示例:

@startuml
class Student {
+ ProgramOfStudy[0..2]: String = "MIS"
- encryptedPW: String {frozen}
# internalID: Integer
~ packagePrivateData: String
}
@enduml
属性作用域
-
实例作用域 (默认): 每个对象都有其自身的值
-
类作用域 (静态): 所有实例共享的单一值

@startuml
class Student {
name: String
{static} count: Integer
}
@enduml
UML 中的键 ⚠️
重要限制: UML 没有内置的键概念。可使用构造型或标记值作为变通方法。

@startuml
class Student {
{pk} id: Integer
{ak1} email: String
- name: String
}
@enduml
🔹 关联与关系
基本关联与多重性
@startuml
class Exercise
class Chapter
Exercise "0..*" -- "1..1" Chapter : 属于
@enduml
解释: 每个练习恰好属于一个章节;一个章节可以包含零个或多个练习。
角色名称
除了(或除了)关联名称外,可在关联端使用角色名称:
@startuml
class Person
class Company
Person "0..*" --> "0..1" Company : 员工/雇主
@enduml
实现: 这个 人员 表将有一个外键 雇主 引用 公司.
可导航性
使用箭头指定遍历方向:

@startuml
class Exercise
class Chapter
Exercise "0..*" --> "1" Chapter
@enduml
-
箭头表示高效遍历方向
-
在 OODB 中:仅以单向指针实现
-
在 RDBMS 中:连接无论哪个方向都有效
具有 的集合类型{有序}

@startuml
class Chapter
class Exercise
Chapter "1" -- "0..*" Exercise : {ordered}
@enduml
-
{有序}: 维持顺序(使用列表,而非集合) -
在 RDBMS 中的实现:添加序列号属性
EXERCISES (
id 主键,
chapter_id 引用 CHAPTERS,
sort_no 整数,
(chapter_id, sort_no) 唯一
)
限定符
限定符使用类似键的机制对相关对象进行分区:

@startuml
class Chapter
class Exercise
Chapter "1" --> "0..1" Exercise : <<限定符>> no: Integer
@enduml
含义: 给定一个章节和一个练习编号,最多返回一个 Exercise。
关联类
当一个关联具有属性或操作时:
@startuml
class Student
class Exercise
class Solution {
date: Date
points: Integer
}
Student "0..*" -- "0..*" Exercise : 已解决
Solution .. Student
Solution .. Exercise
@enduml
-
一个
Solution对象对应一个(学生,练习)组合 -
强制执行:同一个学生不能为同一练习提交两个解决方案
组合与聚合
| 特征 | 组合(*--) |
聚合(o--) |
|---|---|---|
| 符号 | 黑色菱形 | 白色菱形 |
| 关系 | 整体-部分,强拥有关系 | 整体-部分,弱引用 |
| 生命周期 | 整体删除时,部件一同删除 | 部件独立 |
| 多重性 | 整体侧为 1 或 0..1 | 任意 |
| RDBMS 映射 | ON DELETE CASCADE |
标准外键 |
@startuml
class Chapter
class Exercise
Chapter *-- "0..*" Exercise : 组成
Chapter o-- "0..*" Exercise : 聚合
@enduml
🔹 操作和方法
操作声明语法
@startuml
class Calculator {
+ getTotal(studID: Integer, inclExtra: Boolean = true): Float {isQuery=true}
+ {static} getInstance(): Calculator
+ {constructor} Calculator(initialValue: Float)
- recalculate(): void
}
@enduml
参数规范:
[方向] 名称: 类型 [= 默认值]
-
方向:
in(默认),out,inout -
默认值使参数可选
特殊操作构造型
| 构造型 | 目的 |
|---|---|
{isQuery=true} |
保证不会修改状态 |
{构造函数} |
创建并初始化新实例 |
{静态} |
类级别操作,无隐式self |
数据库上下文中的操作
文化冲突: 面向对象强调封装;关系型强调直接数据访问。
实现策略:
| 操作类型 | RDBMS 实现 |
|---|---|
| 简单属性访问 | 直接 SELECT/UPDATE |
| 派生属性(无参数) | 数据库视图 |
| 派生属性(带参数) | 存储过程或应用逻辑 |
| 复杂约束强制执行 | 触发器或应用过程 |
🔹 泛化与继承
基本泛化
@startuml
class Person
class Student
class Professor
Person <|-- Student
Person <|-- Professor
@enduml
抽象类和操作
@startuml
抽象类 Account {
- balance: 浮点数
+ deposit(amount: 浮点数): void
+ {抽象} withdraw(amount: 浮点数): void
}
@enduml
泛化约束
@startuml
class Person
class Student
class Professor
class OtherPerson
Person <|-- Student : <<{互斥, 完整}>>
Person <|-- Professor : <<{互斥, 完整}>>
Person <|-- OtherPerson : <<{互斥, 完整}>>
@enduml
多重分类 / 判别器
@startuml
class Employee
class Staff
class Faculty
class HMO
class NonHMO
Employee <|-- Staff : <<类型>>
Employee <|-- Faculty : <<类型>>
Employee <|-- HMO : <<保险>>
Employee <|-- NonHMO : <<保险>>
@enduml
-
判别器将互斥的特化分组
-
对象在每个判别器维度上只能有一个值
🔹 扩展机制
UML 提供了三种可扩展性机制:
1. 构造型<< >>
通过创建元模型元素的新“子类型”来扩展 UML 语义。
@startuml
class Customer <<实体>> {
- id: 整数
- name: 字符串
}
class MathLibrary <<工具>> {
+ sin(x: 浮点数): 浮点数
+ cos(x: 浮点数): 浮点数
}
@enduml
2. 标记值{键=值}
向模型元素添加自定义属性。
@startuml
class Student {
{author=sb, version=1.0, persistence=persistent}
- id: Integer
}
@enduml
3. 约束{...}
使用自由文本、OCL 或预定义缩写添加语义限制。
@startuml
class Exercise {
- no: Integer
- points: Integer {value >= 0}
{points <= maxPoints}
}
@enduml
🔹 面向数据库设计的 UML:关键考虑因素
将 UML 转换为关系模式
| UML 构造 | 关系实现 |
|---|---|
| 类 | 表 |
| 属性 | 列 |
主键{pk} |
PRIMARY KEY 约束 |
| 关联 (1:*) | “多”端的外键 |
| 关联 (:) | 连接/交集表 |
| 组合 | 外键 +ON DELETE CASCADE |
| 关联类 | 包含复合外键和属性的表 |
| 泛化 | 分开的表(带外键)或单个表加类型鉴别器 |
{有序}关联 |
添加序列列 + 唯一性约束 |
| 限定符 | 复合键或索引列的一部分 |
关键差异:面向对象 vs. 关系型
| 方面 | 面向对象 | 关系型 |
|---|---|---|
| 标识 | 对象引用(代理) | 主键(业务键或代理键) |
| 操作 | 设计核心,封装 | 外部(SQL,存储过程) |
| 封装 | 私有属性,公共接口 | 默认直接访问表 |
| 继承 | 原生语言支持 | 复杂的映射策略 |
| 关系 | 指针/引用 | 外键和连接 |
数据库设计者的实用建议
-
显式建模键: 使用
{主键},{别名1}构造型,因为UML不原生支持键 -
标记持久性: 使用
{持久化}标记值,用于区分数据库类和临时应用类 -
简化操作: 将查询操作映射到视图;将复杂操作映射到存储过程
-
谨慎处理继承: 根据查询模式选择映射策略
-
记录约束: 对业务规则使用OCL或清晰文本约束
-
谨慎使用关联类: 仅当关系具有重要属性时
🎯 快速参考速查表
PlantUML 类图符号概要
@startuml
class <<构造型>> 类名 {
{标记=值}
[+/-/#/~] 名称[多重性]: 类型 [= 值] {属性}
[+/-/#/~] 名称(参数): 返回值 {属性}
}
@enduml
关联符号
@startuml
类A "多重性A" -- "多重性B" 类B : 关联名称
类A *-- 类B ' 组合
类A o-- 类B ' 聚合
类A --> 类B ' 可导航
@enduml
可见性符号
-
+公共 -
-私有 -
#受保护 -
~包
通用属性与约束
-
{静态}/{isQuery=true}/{抽象} -
{值 >= 0}/{异或}/{有序}/{主键}
💡 最终思考: UML类图在概念建模方面非常强大,但请记住它们主要是为软件工程设计的。在使用UML进行数据库设计时,应准备好通过扩展符号(使用构造型、标记值、约束)来捕捉关系概念,如键、规范化和声明性约束,这些概念并非UML面向对象基础的原生部分。
本指南整理自Stefan Brass于2003年在哈雷大学所著的《第6部分:UML类图》。所有图表均采用PlantUML语法格式,以确保与现代工具的兼容性。











