以C++为例详解UML
------ 2024-04-14
文章目录
- 以C++为例详解UML
-
- [1. 什么是UML?](#1. 什么是UML?)
- [2. UML模型结构](#2. UML模型结构)
- [3. UML中类的表示](#3. UML中类的表示)
- [4. UML中类之间的关系](#4. UML中类之间的关系)
-
- [4.1 泛化](#4.1 泛化)
- [4.2 实现](#4.2 实现)
- [4.3 关联](#4.3 关联)
-
- [(1) 单向关联](#(1) 单向关联)
- [(2) 双向关联](#(2) 双向关联)
- [(3) 自关联](#(3) 自关联)
- [(4) 多重关联](#(4) 多重关联)
- [4.4 聚合](#4.4 聚合)
- [4.5 组合](#4.5 组合)
- [4.6 依赖](#4.6 依赖)
- [5. 关联、组合、聚合与依赖的区别](#5. 关联、组合、聚合与依赖的区别)
- [6. 补充笔记,术语说明](#6. 补充笔记,术语说明)
1. 什么是UML?
UML即统一建模语言,它是用于开发、说明、可视化与构建一个面向对象软件的一种方法。UML是面向对象设计的建模工具,独立于任何具体程序设计语言。UML类图将用户所希望描述的事物抽象为类,描述类的内部与多个类之间的设计视图。为之后学习各种设计模式打下基础,因为我们可以通过一种直观的表示方法来描述设计模式。
2. UML模型结构
UML是一种主要由图形符号表示的建模语言,其结构主要包括:
- 视图:从不同角度来表示待建模的系统,视图是由很多图形组成的一个抽象集合;一个系统模型可能有多个视图,每个视图从特定角度来描述系统的特征,比如用户视图、结构视图、行为视图、实现视图等。
- 图:图是UML视图内容的图形,比如用例图、类图、对象图、包图等。
- 模型元素:UML图中使用的一些概念,如类、对象、消息以及各种关系等。
- 通用机制:UML提供的通用机制为模型元素提供额外的注释、语义和扩展机制,允许用户对UML进行扩展。
3. UML中类的表示
类是由一个矩形框表示的,矩形框分为三层。如下图所示:
- 第一层:类的名称,如果该类是抽象类,则使用斜体;
- 第二层:类的属性,即成员变量。格式为:[外部可见性]名称:类型[=默认值];
- 第三层:类的方法,即成员函数。格式为:[外部可见性]名称([参数列表])[:返回值类型];
外部可见性说明:
-
:private(私有)+
:public(公有)#
:protect(保护)
4. UML中类之间的关系
4.1 泛化
含义:类的继承关系
表示:用空心三角形和实线构成,空心三角形指向父类;
举例:狗和猫都属于动物类。
cpp
class Animal {
public:
void breathe() {
cout << "I can breathe" << endl;
}
};
class Dog : public Animal {
public:
void bark() {
cout << "Woof!" << endl;
}
};
class Cat : public Animal {
public:
void meow() {
cout << "Meow!" << endl;
}
};
4.2 实现
含义:类与接口的关系,表示类是接口所有特征和行为的实现。
表示:用空心三角形和虚线表示,空心三角形指向接口。
举例:狗和猫实现了动物的吃和跑的接口。
cpp
class AnimalActions {
public:
virtual void eat() = 0;
virtual void run() = 0;
};
class Dog : public AnimalActions {
public:
void eat() override {
cout << "Dog eats" << endl;
}
void run() override {
cout << "Dog runs" << endl;
}
};
class Cat : public AnimalActions {
public:
void eat() override {
cout << "Cat eats" << endl;
}
void run() override {
cout << "Cat runs" << endl;
}
};
4.3 关联
关联是一种拥有(has a)关系,一个类可以调用另一个类的公有属性和方法。在类中以成员变量的方式表示。
(1) 单向关联
含义:只有一个类知道另一个类的公有属性和方法。
表示:带箭头的直线表示。
举例:员工都有自己的地址。
cpp
class Address {
public:
string street;
string city;
};
class Employee {
public:
Address* address;
};
(2) 双向关联
含义:双方都知道对方的存在,都可以调用对方的公有属性和方法。
表示:用一条直线连接两个类,也可以用双箭头。
举例:老板有自己的员工,员工也有领导自己的老板。
cpp
class Employee; // Forward declaration to resolve circular dependency.
class Boss {
public:
vector<Employee*> employees;
};
class Employee {
public:
Boss* boss;
};
(3) 自关联
含义:自己引用自己
表示:带箭头的直线,指向自己。
举例:二叉树结构体。
cpp
class TreeNode {
public:
int value;
TreeNode* leftChild;
TreeNode* rightChild;
};
(4) 多重关联
含义:对象之间存在多种多重性关联关系。
cpp
class Student;
class Course;
class Enrollment {
public:
Student* student;
Course* course;
string grade;
};
class Student {
public:
vector<Enrollment*> enrollments;
};
class Course {
public:
vector<Enrollment*> enrollments;
};
4.4 聚合
含义:整体与部分的关系,部分离开整体后可以单独存在。常用于类的成员变量。
表示:带空心的菱形和直线(或者带箭头的直线),箭头指向部分。
举例:汽车和轮胎,轮胎是汽车的一部分,但轮胎也可以单独存在。
cpp
class Tire {};
class Car {
public:
Tire* tires[4];
};
4.5 组合
含义:整体和部分的关系,部分离开整体后不可以单独存在,代表整体的对象负责代表部分的对象的生命周期。常用于类的成员变量。
表示:带实心的菱形和直线(带箭头的直线),箭头指向部分。
举例:公司和部分,部门是公司的一部分,但部门不可以单独存在。
cpp
class Department {};
class Company {
public:
vector<Department> departments;
};
4.6 依赖
含义:是一种使用的关系,即一个类的实现需要另一个类的协助。常用于类方法的局部变量、方法参数等。
表示:带箭头的虚线,箭头指向协助的类。
举例:动物依赖水。
cpp
class Water {};
class Animal {
public:
void drink(Water& water) {
cout << "Drinking water" << endl;
}
};
5. 关联、组合、聚合与依赖的区别
- 关联 代表类与类的关系;
- 聚合 和组合 代表整体与部分的关系;
- 依赖 是一种弱的关系,表示一个类的方法的实现需要用到另一个类,但二者之间并没有明显的关系。
6. 补充笔记,术语说明
这些术语是面向对象编程(OOP)中常用的概念,用以描述类(对象)之间的关系。它们在软件设计中非常重要,有助于确定如何设计类的结构、对象之间的交互以及系统的整体架构。下面我将详细解释每个术语、它们之间的区别,并用C++示例和表格来说明。
表格说明
术语 | 英文 | 描述 | C++ 示例 |
---|---|---|---|
依赖 | Dependency | 一个类的实现需要另一个类 | Report 使用 Teacher |
关联 | Association | 两个类互相知道对方,可以是单向或双向的 | Student 与 Teacher |
聚合 | Aggregation | 特殊的关联,代表"整体-部分"关系,部分可以独立存在 | Department 和 Teacher |
组合 | Composition | 特殊的聚合,整体的生命周期控制部分的生命周期,部分不可独立存在 | Classroom 和 Student |
委托 | Delegation | 一个类的功能由另一个类实现,是一种典型的设计模式,用于复用和功能分配 | Graphics 和 Renderer |
术语之间的区别
- 依赖与关联:依赖通常表示一个类在方法中使用了另一个类的对象,关系较为短暂;关联则表示两个类之间有更稳定的连接,通常通过成员变量实现。
- 聚合与组合:聚合表示部分可以离开整体而单独存在,例如教师可以属于多个部门;组合则是更强的关系,部分的生命周期依赖于整体,例如班级和学生,班级销毁时学生也应被销毁。
- 委托:是一种设计模式,一个对象将某个任务委托给另一个对象来执行,以达到代码复用或责任分配的效果。
术语解释与英文全称
-
依赖(Dependency)
- 英文:Dependency
- 描述:一个类依赖于另一个类,如果一个类的方法操纵另一个类的对象。
-
关联(Association)
- 英文:Association
- 描述:两个类互相知道对方,可以是单向或双向的。关联关系的存在意味着一个类的对象可以知道另一个类的一个或多个对象。
-
聚合(Aggregation)
- 英文:Aggregation
- 描述:一种特殊的关联,代表"整体-部分"的关系,但部分可以脱离整体单独存在。
-
组合(Composition)
- 英文:Composition
- 描述:一种更强的聚合关系,整体的生命周期控制部分的生命周期,部分一旦形成就不可与整体分离。
-
委托(Delegation)
- 英文:Delegation
- 描述:一个对象外部暴露的责任被内部的另一个对象实现。这是一种设计模式,常用于实现复用和功能分配。
C++ 示例与表格说明
下面通过一个简单的学校模型来说明这些关系:
cpp
// 依赖关系示例
class Report {
public:
void generateReport(Teacher* teacher) {
// 使用Teacher对象生成报告
}
};
// 关联关系示例
class Student {
public:
void setAdvisor(Teacher* advisor) {
this->advisor = advisor;
}
private:
Teacher* advisor; // 学生知道他们的导师,单向关联
};
// 聚合关系示例
class Department {
public:
void addTeacher(Teacher* teacher) {
teachers.push_back(teacher);
}
private:
std::vector<Teacher*> teachers; // 部门包括多个教师,但教师可以属于多个部门
};
// 组合关系示例
class Classroom {
public:
~Classroom() {
for (auto s : students) {
delete s;
}
}
void addStudent(Student* student) {
students.push_back(student);
}
private:
std::vector<Student*> students; // 班级控制学生的生命周期
};
// 委托关系示例
class Graphics {
public:
void draw() {
renderer->render();
}
private:
Renderer* renderer; // Graphics委托Renderer来进行绘制
};