23种设计模式精解:从入门到实战(四)UML类的画法
2026/9/1 8:55:15 网站建设 项目流程

UML 类图入门:从单个类到类间关系

什么是 UML 类图

UML(Unified Modeling Language,统一建模语言)类图用于描述系统中包含的类以及它们之间的相互关系,帮助简化对系统的理解。它是系统分析和设计阶段的重要产物,也是编码和测试的重要模型依据。

类图主要包含两部分内容:

  1. 如何通过 UML 描述单个类的结构
  2. 如何清晰表述类与类之间的关系

单个类的画法

三层结构

UML 中一个类用矩形表示,分为三层:

  • 上层:类名
  • 中层:属性(成员变量)
  • 下层:方法(成员函数)

属性表示法

格式:【可见性】【属性名称】:【类型】 = {缺省值}

  • 可见性符号:+表示 public,#表示 protected,-表示 private
  • 静态成员:属性名下方加下划线

方法表示法

格式:【可见性】【方法名称】(【参数名:参数类型】):【返回值类型】

  • 多个参数用逗号分隔
  • 无返回值使用void
  • 静态方法同样加下划线

示例:猎人类

以一个猎人(Hunter)类为例,UML 类图如下:

---------------------------------- | Hunter | ---------------------------------- | - m_age : int | | - n_times : static int | ---------------------------------- | + Hunter(age : int) | | + display() : void | | + hunt() : void | | + getHunterCount() : static int| ----------------------------------

对应的 C++ 实现:

#include <iostream> using namespace std; class Hunter { private: int m_age; // 非静态成员变量,属于对象 static int n_times; // 静态成员变量,属于类 public: Hunter(int age) : m_age(age) { n_times++; } static int getHunterCount() { // 静态成员函数,只能访问静态成员 return n_times; } void display() const { cout << "猎人年龄:" << m_age << endl; cout << "猎人总数:" << n_times << endl; } void hunt() { cout << "猎人正在狩猎..." << endl; } }; int Hunter::n_times = 0; // 静态成员变量类外初始化 int main() { Hunter h1(25); Hunter h2(30); h1.display(); cout << "猎人总数:" << Hunter::getHunterCount() << endl; h1.hunt(); return 0; }

关键点对照:m_age是每个猎人独有的(非静态),n_times是所有猎人共享的计数(静态,UML 中下划线标注)。

抽象类的表示

抽象类特征

  • 包含纯虚函数(函数声明后加= 0
  • UML 中类名使用斜体,或标注<<abstract>>
  • 不能实例化对象

示例:Animal 抽象类

---------------------------------- | <<abstract>> | | Animal | ---------------------------------- | # name : string | ---------------------------------- | + Animal(name : string) | | + makeSound() : void = 0 | | + display() : void | ---------------------------------- △ | | ---------------------------------- | Dog | ---------------------------------- | - breed : string | ---------------------------------- | + Dog(name, breed : string) | | + makeSound() : void | | + getBreed() : string | ----------------------------------

Animal是抽象类(makeSound为纯虚函数),Dog继承并实现了纯虚函数,因此可以实例化。

对应的 C++ 实现:

#include <iostream> #include <string> using namespace std; class Animal { // 抽象类 protected: string name; public: Animal(string n) : name(n) {} virtual void makeSound() const = 0; // 纯虚函数 virtual void display() const { cout << "动物名称:" << name << endl; } virtual ~Animal() {} }; class Dog : public Animal { // 具体类 private: string breed; public: Dog(string n, string b) : Animal(n), breed(b) {} void makeSound() const override { cout << name << "(品种:" << breed << ")在叫:汪汪汪!" << endl; } void display() const override { cout << "狗 - 名称:" << name << ",品种:" << breed << endl; } }; int main() { // Animal a("动物"); // 错误:抽象类不能实例化 Dog dog("小白", "金毛"); Animal* animal = &dog; // 父类指针指向子类对象 animal->display(); animal->makeSound(); return 0; }

类之间的六种关系

单个类的画法只是基础,类图真正的价值在于描述类与类之间的关系。常见的有六种:

关联(Association)

类之间的结构化引用关系,一个类的对象持有另一个类的对象作为成员。

  • 表示法:实线箭头A --> B
  • 示例:猎人持有猎枪,Hunter类中包含Gun类型的成员变量
Hunter ----------> Gun

依赖(Dependency)

一个类在某个地方使用了另一个类(如函数参数、局部变量),是最弱的关系。

  • 表示法:虚线箭头A ..> B
  • 示例:猎人的hunt()方法接收Forest类型的参数
Hunter ..> Forest

泛化(Generalization)

即继承关系,子类继承父类的属性和行为。

  • 表示法:空心三角实线箭头,指向父类子类 --|> 父类
  • 示例:Dog继承Animal
Dog --|> Animal

实现(Realization)

类实现接口(抽象类)中定义的纯虚函数。

  • 表示法:空心三角虚线箭头子类 ..|> 接口
  • 示例:Dog实现Animal接口的makeSound()
Dog ..|> Animal

在 C++ 中,泛化和实现通常都通过继承体现:继承有具体实现的父类是泛化,继承只有纯虚函数的抽象类是实现。

聚合(Aggregation)

整体与部分的关系,但部分可以脱离整体独立存在

  • 表示法:空心菱形 + 实线,菱形在整体端整体 o-- 部分
  • 示例:战队包含队员,队员离开战队后仍然存在
Team o-- Member

组合(Composition)

整体与部分的关系,但部分不能脱离整体独立存在,生命周期由整体管理。

  • 表示法:实心菱形 + 实线,菱形在整体端整体 *-- 部分
  • 示例:汽车包含发动机,发动机离开汽车没有独立意义
Car *-- Engine

六种关系速查表

关系表示法强度典型场景
关联A --> B类成员引用另一个类
依赖A ..> B函数参数、局部变量
泛化`子类 –> 父类`
实现`类 …> 接口`
聚合整体 o-- 部分整体-部分,部分可独立
组合整体 *-- 部分整体-部分,部分不可独立

完整示例

用一个简单的系统把上面的关系串起来:

Team o-- Hunter (聚合:战队包含猎人,猎人可独立存在) Hunter --> Gun (关联:猎人持有猎枪) Hunter ..> Forest (依赖:狩猎方法接收森林参数) Hunter --|> Person (泛化:猎人继承自人) Dog ..|> Animal (实现:狗实现动物接口) Car *-- Engine (组合:汽车包含发动机,不可独立)

这张图涵盖了六种关系,阅读时从箭头和菱形的形状就能判断关系类型。

小结

UML 类图的学习分两步:

  1. 掌握单个类的画法:三层结构、属性/方法表示法、可见性符号、静态成员和抽象类的特殊标注
  2. 理解类间六种关系:关联、依赖、泛化、实现、聚合、组合,每种关系对应不同的箭头或菱形符号

画类图时,先识别系统中有哪些类,再确定类之间的关系,最后用标准符号表达。熟练之后,类图能帮你在写代码之前就把系统结构想清楚,减少后期重构的代价。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询