UML 类图

面向对象程序设计(Java)

掌握类图元素与关系,规范表达面向对象设计

1.1 UML基础概念与类图定位

UML(Unified Modeling Language,统一建模语言)是一种标准化的图形建模语言,用于可视化、描述、构建和文档化软件系统的产物。

UML的定义与用途

  • 定义:一种通用的、标准化的建模工具,不是编程语言
  • 可视化:通过图形方式直观展示系统结构和行为
  • 规范化:提供标准化的表达方式,减少沟通歧义
  • 文档化:为系统设计提供完整、准确的文档记录

UML发展历史

  • 1995年:Booch、Rumbaugh和Jacobson三位方法学家开始统一方法
  • 1997年:UML 1.0被对象管理组织(OMG)采纳为标准
  • 2005年:UML 2.0发布,引入更丰富的建模能力
  • 2015年:UML 2.5发布,目前最新的稳定版本

类图在UML中的定位

类图是UML中的静态结构图,用于描述系统中类的静态结构以及它们之间的各种关系。与描述系统行为的动态图(如序列图、活动图)不同,类图关注的是系统的"快照",展示系统在某一时刻的结构组成。

最小可用类图示例

@startuml
class Student {
  - id : int
  + name : String
  + getName() : String
  + setName(n : String) : void
}
@enduml
渲染结果(SVG)
UML渲染

类图用于静态结构表达;属性与方法区分清晰,采用可见性标记描述访问约束。

2.1 类图核心要素:类、关系与接口

类图由三大核心要素构成:类(Class)、关系(Relationship)和接口(Interface)。这些要素共同描述了系统的静态结构。

1. 类(Class)的表示方法

类是类图的核心元素,由三部分组成:

  • 名称栏:类的名称
  • 属性栏:类的属性/字段
  • 方法栏:类的操作/方法

2. 类之间的关系

类之间可以通过多种关系相互连接,每种关系有不同的语义:

  • 关联(Association):类之间的结构关系
  • 聚合(Aggregation):整体与部分的关系,部分可独立存在
  • 组合(Composition):强聚合,部分不能独立存在
  • 继承(Inheritance):一般与特殊的关系
  • 实现(Realization):接口与实现类的关系
  • 依赖(Dependency):一个类使用另一个类

3. 接口(Interface)的表示方式

接口是一种特殊的类,它定义了一组操作规范但没有实现,用于表达行为约定和抽象概念。

类是类图的核心元素,关系连接类形成结构,接口定义行为规范。

2.2 类成员可见性与抽象设计

深入理解类成员的可见性、抽象类与接口的使用。

类成员与可见性

可见性符号用于控制类成员的访问级别:

  • +:公有(public) - 所有类可访问
  • -:私有(private) - 仅本类可访问
  • #:受保护(protected) - 本类、子类及同包类可访问
  • ~:包级私有(package private) - 同包类可访问

类成员示例

@startuml
class Account {
  - id : long
  + owner : String
  # balance : BigDecimal
  + deposit(amount : BigDecimal) : void
  + withdraw(amount : BigDecimal) : boolean
}
@enduml
渲染结果(SVG)
UML渲染

抽象类与接口

@startuml
interface AuthService {
  + login(u : String, p : String) : boolean
}
abstract class Person {
  + id : int
  + getId() : int
}
class Student extends Person {
  + name : String
}
Student ..|> AuthService
@enduml
渲染结果(SVG)
UML渲染

接口用于行为约定;抽象类表达抽象通用性;实现关系以空心三角+虚线表示。

3.1 类元素语法:属性与方法

掌握类图元素的完整语法格式,能够更精确地表达设计意图。

属性的完整语法

可见性 名称 : 类型 [多重性] = 初始值 {属性特性}

  • 可见性:+、-、#、~
  • 多重性:[1]、[0..1]、[0..*]、[1..*]
  • 属性特性:{readOnly}、{derived}、{static}

方法的完整语法

可见性 名称 (参数列表) : 返回类型 {方法特性}

  • 参数列表:参数名 : 类型 [默认值]
  • 方法特性:{query}、{static}、{abstract}

属性与方法示例

@startuml
class Product {
  - id : long [1]
  - name : String [1]
  - price : double [1] = 0.0
  - description : String [0..1]
  + {static} TAX_RATE : double = 0.08
  + {query} calculateTax() : double
  + {static} fromJson(json : String) : Product
  + {abstract} validate() : boolean
}
@enduml
渲染结果(SVG)
UML渲染

属性和方法的完整语法提供了精确表达设计意图的能力,多重性和特性标记是关键要素。

4.1 强关系(结构性关系)

强关系表示类之间紧密的结构性依赖,修改一方会直接影响另一方。按照依赖强度从强到弱依次为:继承、实现、组合。

继承关系 - 最强

定义:表示"is-a"关系,子类完全依赖父类。

特点:修改父类会直接影响子类,子类继承父类的所有属性和方法。

表示方法:实线空心三角箭头,箭头指向父类。

实现关系 - 最强

定义:表示类完全依赖接口定义。

特点:必须实现所有接口方法,接口变更会影响实现类。

表示方法:虚线空心三角箭头,箭头指向接口。

组合关系 - 很强

定义:表示整体与部分的关系,部分不能独立于整体存在。

特点:生命周期强绑定,整体销毁时部分也随之销毁(如:汽车-引擎)。

表示方法:实心菱形端点的实线,菱形端点连接整体类。

@startuml
class Animal
class Dog extends Animal
interface Runnable
Dog ..|> Runnable
class Car
class Engine
Car *-- Engine
@enduml
渲染结果(SVG)
UML渲染

强关系体现了类之间的结构性依赖,设计时需要谨慎考虑,因为修改会带来连锁影响。

4.2 弱关系(行为性关系)

弱关系表示类之间较为松散的连接,修改一方对另一方的影响较小。按照依赖强度从强到弱依次为:聚合、关联、依赖。

聚合关系 - 中等强度

定义:表示整体与部分的关系,部分可以独立于整体存在。

特点:"has-a"关系,生命周期独立(如:部门-员工)。

表示方法:空心菱形端点的实线,菱形端点连接整体类。

关联关系 - 较弱

定义:表示对象间的独立存在,只是相互引用。

特点:通常是长期关系,对象可以独立存在(如:学生-课程)。

表示方法:实线连接,可带箭头表示导航方向。

依赖关系 - 最弱

定义:表示临时性的使用关系。

特点:通常是方法参数、局部变量(如:方法调用时依赖某个类)。

表示方法:虚线箭头,箭头指向被依赖的类。

@startuml
class Department
class Employee
class Student
class Course
class OrderService
class EmailService
Department o-- "1..*" Employee
Student "0..*" -- "0..*" Course
OrderService ..> EmailService
@enduml
渲染结果(SVG)
UML渲染

弱关系体现了类之间的行为性连接,设计时优先选择较弱的关系,以提高系统的灵活性和可维护性。

4.3 关联关系详解

关联关系是UML类图中最基本的关系类型,表示类之间的结构化连接。

关联关系(Association)

定义:表示类之间的结构化连接,描述对象之间的链接关系。

特点:是一种"has-a"关系,表示一个对象知道另一个对象的存在。

表示方法:实线连接,可带箭头表示导航方向,可标注多重性。

关联关系的类型

双向关联:两个类互相知道对方的存在,用无箭头的实线表示。

单向关联:只有一个类知道另一个类的存在,用带箭头的实线表示。

自关联:类与自身关联,表示类内部对象之间的关系。

多重性表示

1:恰好一个

0..1:零个或一个

* 或 0..*:零个或多个

1..*:一个或多个

n:固定数量

m..n:范围数量

@startuml
class Teacher
class Student
class Course

' 双向关联
Teacher "1" -- "0..*" Student : teaches >

' 单向关联
Teacher --> Course : teaches >

@enduml
渲染结果(SVG)
UML渲染

关联关系是类图中最常用的关系,正确使用多重性可以精确表达类之间的数量约束。

4.4 聚合关系详解

聚合关系是关联关系的特殊形式,表示整体与部分的关系,但部分可以独立存在。

聚合关系(Aggregation)

定义:表示"has-a"关系的特殊形式,表示整体与部分的关系,但部分可以独立存在。

特点:部分对象的生命周期不依赖于整体对象,可以独立存在。

表示方法:空心菱形端点的实线,菱形端点连接整体类。

聚合关系的特征

生命周期独立:部分对象可以在整体对象创建之前存在,也可以在整体对象销毁后继续存在。

共享性:一个部分对象可以同时属于多个整体对象。

弱耦合:整体和部分之间的关系相对松散。

聚合关系的应用场景

部门与员工:部门包含员工,但员工可以独立存在,也可以属于多个部门。

汽车与轮胎:汽车有轮胎,但轮胎可以独立存在,也可以安装到其他汽车上。

团队与成员:团队由成员组成,但成员可以离开团队,也可以加入其他团队。

@startuml
class Department {
  - name : String
}
class Employee {
  - id : int
  - name : String
}

' 聚合关系:部门包含员工,但员工可以独立存在
Department o-- Employee : contains >

@enduml
渲染结果(SVG)
UML渲染

聚合关系强调了整体与部分的关系,但部分可以独立存在,这是与组合关系的主要区别。

4.5 组合关系详解

组合关系是聚合关系的特殊形式,表示更强的整体与部分关系,部分不能独立存在。

组合关系(Composition)

定义:表示更强的"has-a"关系,部分对象的生命周期依赖于整体对象。

特点:部分对象不能独立存在,整体对象销毁时,部分对象也随之销毁。

表示方法:实心菱形端点的实线,菱形端点连接整体类。

组合关系的特征

生命周期依赖:部分对象的生命周期完全依赖于整体对象。

独占性:一个部分对象在同一时间只能属于一个整体对象。

强耦合:整体和部分之间的关系非常紧密。

组合关系的应用场景

房子与房间:房子包含房间,房间不能独立存在,房子销毁时房间也随之销毁。

公司与部门:公司由部门组成,部门不能独立于公司存在。

文档与章节:文档由章节组成,章节不能独立于文档存在。

组合与聚合的区别

生命周期:组合中部分依赖整体,聚合中部分独立于整体。

共享性:组合中部分不能共享,聚合中部分可以共享。

表示方法:组合用实心菱形,聚合用空心菱形。

@startuml
class House {
  - address : String
}
class Room {
  - area : double
  - type : String
}
class Door {
  - material : String
}

' 组合关系:房子包含房间和门,房间和门不能独立存在
House *-- Room : contains >
House *-- Door : has >

@enduml
渲染结果(SVG)
UML渲染

组合关系是最强的结构关系,表示部分的生命周期完全依赖于整体,体现了"部分不能脱离整体而存在"的语义。

4.6 依赖关系详解

依赖关系是UML类图中最弱的关系,表示一个类使用另一个类的临时性关系。

依赖关系(Dependency)

定义:表示一个类使用另一个类,通常是一种临时性的、较弱的关系。

特点:通常表现为一个类的方法使用另一个类作为参数、返回值或局部变量。

表示方法:虚线箭头,箭头指向被依赖的类。

依赖关系的表现形式

参数依赖:一个类的方法使用另一个类作为参数。

返回值依赖:一个类的方法返回另一个类的对象。

局部变量依赖:一个类的方法中定义了另一个类的局部变量。

静态方法调用:一个类调用另一个类的静态方法。

依赖关系的应用场景

服务调用:业务类调用服务类的方法。

工具类使用:业务类使用工具类进行辅助操作。

工厂模式:客户端类依赖工厂类创建对象。

依赖关系与其他关系的区别

临时性:依赖关系通常是临时的,而关联、聚合、组合是长期的结构关系。

弱耦合:依赖关系表示较弱的耦合,而其他关系表示较强的耦合。

使用方式:依赖关系表示"使用"关系,其他关系表示"拥有"关系。

@startuml
class OrderProcessor {
  + processOrder(order : Order) : void
}
class Order {
  - items : List<OrderItem>
}
class EmailService {
  + sendEmail(to : String, content : String) : void
}

' 依赖关系:订单处理器依赖于订单和邮件服务
OrderProcessor ..> Order : uses >
OrderProcessor ..> EmailService : uses >

@enduml
渲染结果(SVG)
UML渲染

依赖关系是最弱的关系,表示临时性的使用关系,合理使用依赖关系可以降低系统的耦合度。

4.7 继承关系详解

5. 继承关系(Inheritance/Generalization)

定义:表示"is-a"关系,子类继承父类的属性和方法。

特点:子类是父类的特化,具有父类的所有特性,并可以添加新的特性。

表示方法:实线空心三角箭头,箭头指向父类。

继承关系的核心特性

  • 传递性:如果B继承A,C继承B,则C间接继承A
  • 单根性:Java中类只能单继承,但可以多实现接口
  • 访问控制:子类可以访问父类的protected和public成员
  • 多态性:子类对象可以当作父类对象使用
@startuml
class Vehicle {
  # speed : double
  + start() : void
  + stop() : void
}
class Car extends Vehicle {
  - doors : int
  + openTrunk() : void
}
class Motorcycle extends Vehicle {
  - type : String
  + doWheelie() : void
}

' 继承关系:汽车和摩托车继承自车辆
Car --|> Vehicle
Motorcycle --|> Vehicle

@enduml
渲染结果(SVG)
UML渲染

继承是面向对象编程的核心机制,通过继承可以实现代码复用和建立清晰的类层次结构。设计时应遵循"里氏替换原则",确保子类可以替换父类而不影响程序正确性。

4.8 实现关系详解

实现关系(Realization/Implementation)

定义:表示类实现接口,接口定义了一组操作,类提供这些操作的具体实现。

特点:类必须实现接口中定义的所有方法,是一种契约关系。

表示方法:虚线空心三角箭头,箭头指向接口。

实现关系的核心特性

  • 多实现性:一个类可以实现多个接口,弥补单继承的不足
  • 契约性:接口定义了行为契约,实现类必须遵守
  • 抽象性:接口只定义行为规范,不包含实现细节
  • 多态性:通过接口引用可以调用不同实现类的方法
@startuml
interface Drawable {
  + draw() : void
  + resize(scale : double) : void
}
interface Movable {
  + move(dx : double, dy : double) : void
}
class Shape {
  - x : double
  - y : double
}
class Circle extends Shape implements Drawable, Movable {
  - radius : double
  + draw() : void
  + resize(scale : double) : void
  + move(dx : double, dy : double) : void
}

' 实现关系:圆形实现了可绘制和可移动接口
Circle ..|> Drawable
Circle ..|> Movable

@enduml
渲染结果(SVG)
UML渲染

继承与实现关系对比

对比项 继承关系 实现关系
语义 is-a关系 can-do关系
数量限制 单继承 多实现
内容 属性+方法 抽象方法
表示方法 实线空心三角 虚线空心三角

实现关系提供了灵活的多态机制,通过接口可以定义系统的行为规范,降低类之间的耦合度。设计时应优先使用接口而非具体类,遵循"面向接口编程"的原则。

3.2 关系语法与多重性表示

掌握类之间关系的语法表示,准确表达类之间的连接方式。

关系语法示例

@startuml
' 接口
interface Payable {
    +getSalary(): double
}

' 抽象类
abstract class Person {
    -name: String
    -age: int
    +getName(): String
}

' 具体类
class Employee {
    -employeeId: String
    +getSalary(): double
}

class Department {
    -deptName: String
    +addEmployee(emp: Employee): void
}

class Project {
    -projectName: String
    +startProject(): void
}

class Task {
    -taskName: String
    +complete(): void
}

' 工具类
class Calculator {
    +calculateBonus(salary: double): double
}

' 继承关系
Employee --|> Person

' 实现关系
Employee ..|> Payable

' 关联关系
Employee "1" -- "*" Project : works on >

' 聚合关系
Department "1" o-- "*" Employee : contains >

' 组合关系  
Project "1" *-- "1..*" Task : consists of >

' 依赖关系
Employee ..> Calculator : uses >

@enduml
渲染结果(SVG)
UML渲染

掌握完整语法有助于精确表达设计意图,多重性和关系类型是关键要素。

5.1 类图绘制规范与最佳实践

保持命名统一、关系方向合理、标注多重性与可见性、适度分组。关注可读性与一致性。

规范示例

@startuml
package app {
  class Controller
  class Service
  class Repository
}
Controller --> Service
Service --> Repository
class Utils {
  {static} version : String
  {static} now() : Date
}
@enduml
渲染结果(SVG)
UML渲染

采用包分组、明确依赖方向、区分静态成员,保证图面简洁与表达准确。

5.2 实战案例:电商系统订单模块设计

通过一个完整的电商系统订单模块,展示类图在实际项目中的应用。

需求分析

  • 客户可以下订单,一个订单包含多个订单项
  • 每个订单项对应一个商品,包含数量和单价
  • 订单需要支付,支持多种支付方式
  • 系统需要记录订单状态和操作日志

类图设计

@startuml
package 电商系统 {
  class Customer {
    - id : long
    - name : String
    - email : String
    + register() : boolean
    + login(password : String) : boolean
    + placeOrder(items : List) : Order
  }
  
  class Order {
    - orderNumber : String
    - orderDate : Date
    - totalAmount : BigDecimal
    + calculateTotal() : BigDecimal
    + addItem(item : OrderItem) : void
    + removeItem(item : OrderItem) : void
  }
  
  class OrderItem {
    - quantity : int
    - unitPrice : BigDecimal
    + getSubtotal() : BigDecimal
  }
  
  class Product {
    - id : long
    - name : String
    - price : BigDecimal
    - stock : int
    + updateStock(quantity : int) : void
    + isAvailable() : boolean
  }
  
  class PaymentResult {
    - success : boolean
    - transactionId : String
    - message : String
  }
  
  interface PaymentService {
    + processPayment(amount : BigDecimal) : PaymentResult
  }
  
  class CreditCardPayment implements PaymentService {
    + processPayment(amount : BigDecimal) : PaymentResult
  }
}

Customer "1" -- "0..*" Order : places >
Order "1" *-- "1..*" OrderItem : contains >
OrderItem "1" -- "1" Product : refers to >
Order ..|> PaymentService : uses >
@enduml
渲染结果(SVG)
UML渲染

设计解析

  • Customer与Order:一对多关联关系,一个客户可以有多个订单
  • Order与OrderItem:组合关系,订单由多个订单项组成,订单项不能独立存在
  • OrderItem与Product:关联关系,订单项引用一个商品
  • Order与PaymentService:依赖关系,订单处理时需要使用支付服务

从需求分析到类图设计,识别核心类、定义属性方法、建立关系是关键步骤。

6.1 交互实践:PlantUML编辑器

在下方编辑区修改PlantUML代码,点击运行或直接输入实时预览;可选择导出为SVG或PNG。

待运行
UML图预览

6.2 类图与其他UML图的协作关系

类图是UML中的静态结构图,与其他UML图相互补充,共同构成完整的系统模型。

类图与序列图

  • 类图:定义静态结构,展示类及其关系
  • 序列图:展示对象间的动态交互过程
  • 关系:类图中的类对应序列图中的对象,类图中的方法对应序列图中的消息

类图与用例图

  • 用例图:描述系统功能需求,从用户视角展示系统功能
  • 类图:实现用例所需的内部结构
  • 关系:用例驱动类的设计,每个用例可能对应一组协作的类

类图与组件图

  • 类图:展示系统内部微观结构
  • 组件图:展示系统更高层次的组织结构
  • 关系:组件由一组类组成,类图是组件图的细化

类图与活动图

  • 活动图:描述业务流程或算法流程
  • 类图:活动图中涉及的对象类型
  • 关系:活动图中的操作通常对应类图中的方法

建模工具使用建议

  • Enterprise Architect:功能全面,适合大型项目
  • Visual Paradigm:界面友好,学习曲线平缓
  • PlantUML:文本式建模,适合版本控制和协作
  • StarUML:开源免费,适合中小型项目

类图设计最佳实践

  • 保持简洁:避免在单个类图中展示过多信息
  • 关注重点:根据受众调整展示的详细程度
  • 遵循标准:使用标准UML符号和约定
  • 合理分组:使用包或命名空间组织相关类
  • 明确关系:准确表示类之间的关系和多重性

常见误区

  • 过度设计:创建不必要的类和关系
  • 细节过多:在类图中包含过多实现细节
  • 关系混淆:错误使用关系类型(如混淆聚合和组合)
  • 忽略约束:不标注重要的约束条件
  • 不一致性:命名和表示方式不统一

类图是面向对象设计的重要工具,掌握它将帮助您更好地设计、沟通和实现软件系统。

1 / X