PlantUML 类图高级用法:抽象、接口、关联、依赖、限定符

puml.online

类图是最常用却最容易被画错的 UML 图。零基础谁都看得懂,复杂了经常因为箭头画错让评审反复确认。这是一篇把类图所有关系一次说清楚的文章。

类成员可见性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@startuml
class User {
-id: Long
-name: String
#email: String
~passwordHash: String
+createdAt: LocalDate
+login()
+logout()
{static} +hashPassword()
{abstract} #validateEmail()
}

note right of User
- private (减号)
# protected (井号)
~ package (波浪号)
+ public (加号)
{static} 静态
{abstract} 抽象
end note
@enduml
修饰 含义
- private
# protected
~ package / internal
+ public
{static} 静态方法
{abstract} 抽象方法
{method} 普通方法(一般省略)

类、抽象类、接口、枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@startuml
abstract class Animal {
+name: String
{abstract} +makeSound()
}

class Dog {
+breed: String
+makeSound()
}

class Cat {
+indoor: boolean
+makeSound()
}

interface Pet {
+play()
}

interface Named {
+getName(): String
}

enum Color {
BLACK
WHITE
TABBY
}

Animal <|-- Dog
Animal <|-- Cat
Animal ..|> Named
Pet ..|> Dog
Pet ..|> Cat
@enduml

要点:

  • abstract class 抽象类,渲染成斜体
  • class 普通类
  • interface 接口,<> stereotype + 圆头
  • enum 枚举
  • <|-- 继承(实线 + 空心三角)
  • ..|> 实现(虚线 + 空心三角)

类之间的关系:5 种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@startuml

class Car
class Engine
class Driver
class Wheel
class SteeringWheel

Car "1" *-- "4" Wheel : 整体-部分
Car "1" o-- "1" Engine : 弱聚合
Car "1" --> "1" SteeringWheel : 关联
Driver --> Car : 依赖
Car ..> Driver : 泛化(少见)

note bottom of Car
*-- : composition(组合)— 整体消失则部分消失
o-- : aggregation(聚合)— 整体消失部分可以单独存在
--> : association(关联)— 长期持有关系
..> : dependency(依赖)— 临时使用
--|> : generalization(泛化)— 子类
..|> : realization(实现)— 接口
end note
@enduml

记忆口诀:

关系 关键字 含义 代码表现
组合 *-- 整体 / 部分,整体消失则部分消失 内部 new
聚合 o-- 整体 / 聚合,整体消失部分独立 构造器注入
关联 --> 长期持有 字段引用
依赖 ..> 临时使用 方法参数 / 局部变量
泛化 --|> 子类继承父类 extends
实现 ..|> 类实现接口 implements

关联上的修饰:限定符、角色、可见性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@startuml
class Company
class Employee

Company "1..*" o-- "*" Employee : employs

note right of Company
1..* 表示多重性(multiplicity)
角色名 employs 是关联的名字
- 紧挨着 Employee 的位置可以标可见性(如 + - #)
end note

Company --> "- boss +name" Employee : 角色与可见性
@enduml

多重性是 min..max

  • 1 恰好 1
  • 0..1 0 或 1
  • * 0 或多(不指定上限)
  • 1..* 至少 1

角色名用括号写靠近目标类:- boss 表示 “Employee 在 Company 上是 private 的 boss 角色”。

嵌套类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@startuml
class Order {
-id: Long
-items: List<Item>
+checkout()
}

class OrderStatus {
+PENDING
+PAID
+SHIPPED
+DELIVERED
}

Order +-- OrderStatus : 内嵌枚举
@enduml

+-- 表示 Order contain OrderStatus,渲染成 inner+outer 嵌套。

包依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@startuml
package "com.app" {
package "domain" {
class Order
class Customer
}
package "service" {
class OrderService
class CustomerService
}
package "controller" {
class OrderController
}
}

OrderService --> Order : 引用
OrderController --> OrderService : 调用
CustomerService --> Customer : 引用
@enduml

package 多层嵌套,渲染成嵌套矩形。多用于「依赖图」「模块拓扑」。

抽象方法和实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@startuml
abstract class Handler {
{abstract} +handle(req: Request): Response
+next(req: Request): Response
}

class AuthHandler {
+handle(req: Request)
}

class LoggingHandler {
+handle(req: Request)
}

Handler <|-- AuthHandler
Handler <|-- LoggingHandler

note bottom of Handler
{abstract} 标识抽象方法
子类必须 override
end note
@enduml

组合 vs 聚合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@startuml
class House {
-address: String
+rooms: List<Room>
}

class Room {
-area: int
}

class Garage

House "1" *-- "*" Room : 组合
House "0..1" o-- "0..1" Garage : 聚合

note right of Garage
组合:House 拆除后 Room 不存在
聚合:House 拆除后 Garage 可以挪走再用
end note
@enduml

经验:判断是组合还是聚合,就问「整体不存在了,部分能不能独立存在」——能独立就用 o-- 聚合,必须依赖就用 *-- 组合。

关联类(中间表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@startuml

class Student
class Course
class Enrollment {
-grade: Float
-enrolledAt: Date
}

Student "1" --- "*" Enrollment
Course "1" --- "*" Enrollment
(Student, Course) .. Enrollment

note right of Enrollment
Enrollment 是 Student-Course 关联类
它有自己的属性(grade、enrolledAt)
end note
@enduml

关联类用 --- 关联两边,再 .. 引到中间类。常见于「关联有自己属性」的场景,如 Enrollment / 选课记录

完整实战:电商订单领域模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
@startuml
skinparam classAttributeIconSize 0

abstract class AggregateRoot {
+id: Long
{abstract} +validate()
}

class Order {
-status: OrderStatus
-items: List<OrderItem>
-customerId: Long
+place()
+cancel()
+ship()
+complete()
+totalAmount(): Money
}

class OrderItem {
-productId: Long
-quantity: int
-unitPrice: Money
}

class Money {
-amount: BigDecimal
-currency: String
}

class Customer {
-name: String
-email: String
}

class Product {
-sku: String
-name: String
-price: Money
}

enum OrderStatus {
PENDING
PAID
SHIPPED
DELIVERED
CANCELLED
REFUNDED
}

interface Auditable {
+createdAt: Instant
+updatedAt: Instant
}

AggregateRoot <|-- Order
Auditable ..|> Order
Auditable ..|> Customer

Order "1" *-- "1..*" OrderItem
OrderItem "1" --> "1" Product
Order "1" --> "1" Customer
Order "1" --> "1" OrderStatus
OrderItem "1" --> "1" Money
Product "1" --> "1" Money

note bottom of Order
订单模型核心要点:
- Order 是聚合根
- 包含多个 OrderItem
- 引用 Customer 和 Product 但不持有
- 状态枚举集中表达生命周期
end note
@enduml

评审 checklist

  • 每个类都标了可见性(- / # / +)?
  • 关系箭头方向正确?(A 持有 B 时画 A --> B,反过来则反向)
  • 区分清楚了泛化 / 实现 / 关联 / 聚合 / 组合 / 依赖?
  • 不要为每个类都画 5 种关系——只画跟领域语义相关的
  • 接口用 <<interface>> 或专门的 interface 关键字
  • 抽象方法标了 {abstract} 或方法名字体
  • 抽象类用 abstract class
  • 枚举用 enum
  • 抽象类名以 Abstract 开头(如果项目代码有约定)

常见反模式

关系过度

1
2
3
4
5
6
7
class A
class B
class C
A --> B
B --> C
C --> A
@enduml

A → B → C → A 循环依赖。一张图同时画「运行时依赖」和「编译时依赖」会让评审混乱。

省略可见性

1
2
3
4
5
6
class User {
id
name
email
login()
}

没标可见性等于让评审自己猜「这些字段 public 还是 private」。所有字段都标

互相依赖

1
2
3
4
5
class Foo
class Bar

Foo --> Bar : holds
Bar --> Foo : holds

互引用经常意味着该拆模块,或两个类应该合并。

一句话总结

类图 5 种关系 + 4 种可见性 + 5 种结构类型,构成 UML 类图的全部。**关系方向、可见性、语义(聚合 vs 组合 vs 关联)**三件事画对,类图就专业了。

  • 标题: PlantUML 类图高级用法:抽象、接口、关联、依赖、限定符
  • 作者: puml.online
  • 创建于 : 2026-07-29 15:25:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-class-advanced/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。