作为程序员,在学习或使用面向对象编程(OOP)时,类与类之间的关系是一个绕不开的话题。合理地建模类之间的关系,不仅能让代码更清晰,也能显著提升系统的可维护性和扩展性。
文章目录
- 一、为什么要理解类之间的关系?
- 二、类与类之间的六种常见关系
- 三、依赖关系(Dependency)
- 1、概念
- 2、示例
- 3、特点
- 四、关联关系(Association)
- 1、概念
- 2、示例
- 2.1双向关联
- 2.2单向关联
- 2.3自关联
- 3、特点
- 五、聚合关系(Aggregation)
- 1、概念
- 2、示例
- 3、特点
- 六、组合关系(Composition)
- 1、概念
- 2、示例
- 3、特点
- 七、继承关系(Inheritance)
- 1、概念
- 2、示例
- 3、特点
- 八、实现关系(Implementation)
- 1、概念
- 2、示例
- 3、特点
- 九、关系强度对比总结
一、为什么要理解类之间的关系?
在真实世界中,对象之间往往不是孤立存在的,例如:
- 学生属于某个班级
- 汽车由发动机、轮胎等组成
- 程序员是一种“人”
面向对象设计正是通过类与类之间的关系来描述这些现实世界的联系。理解这些关系,有助于:
- 建立合理的领域模型
- 避免“上帝类”“面条代码”
- 更好地遵循 SOLID等设计原则
- 读懂 UML 类图和优秀框架源码
二、类与类之间的六种常见关系
从弱到强、从“使用”到“拥有”,常见的类关系主要包括以下几种:
- 依赖(Dependency)
- 关联(Association)
- 聚合(Aggregation)
- 组合(Composition)
- 继承(Inheritance)
- 实现(Implementation)
下面将逐一介绍。
三、依赖关系(Dependency)
1、概念
依赖关系是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。在代码中,某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类(被依赖类)中的某些方法来完成一些职责。
依赖关系表示:
一个类在“使用”另一个类,但这种关系是临时的、不稳定的。
通常体现在:
- 方法参数
- 局部变量
- 返回值
2、示例
👉UML 表示:在 UML 类图中,依赖关系使用带箭头的虚线来表示,箭头从使用类指向被依赖的类。
classDriver{publicvoiddrive(Carcar1){car1.move();}}这里Driver依赖Car,但并不持有它。
3、特点
- 生命周期无关
- 关系最弱
- 修改被依赖类,可能影响使用方
四、关联关系(Association)
1、概念
关联关系的核心是连接。它意味着一个类的对象(实例)可以“导航”到另一个类的对象,通常是通过属性(成员变量)来持有对另一个对象的引用。这种关系是双向的,但具体的实现(导航性)可以是单向的。
关联关系表示:
一个类“知道”另一个类,并将其作为成员变量。
这是一种长期存在的关系。
2、示例
2.1双向关联
在UML类图中,双向关联用一个不带箭头的直线表示。下图中在Student类中维护一个List<Course>,表示一个学生可以选择多门课程;在Course类中维护一个Student类型的成员变量表示这门被哪个学生所选。
2.2单向关联
classStudent{privateAddressaddress;}每个学生都有一个家庭地址,学生和地址之间存在单向关联关系。
2.3自关联
自关联在UML类图中用一个带有箭头且指向自身的线表示。上图的意思就是Node类包含类型为Node的成员变量,也就是“自己包含自己”,自己指向自己。
3、特点
- 双方生命周期可以独立
- 可以是单向或双向
- 是一种结构性关系
五、聚合关系(Aggregation)
1、概念
聚合关系是关联关系的一种,是强关联关系,是整体和部分之间的关系。
聚合关系也是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在。如下示例所示,部门解散后,员工仍然存在。
聚合是关联关系的一种特例,表示:
“整体 - 部分”关系,但部分可以独立于整体存在。
2、示例
👉 UML 表示:空心菱形 + 实线
classDepartment{privateList<Employee>employees;}部门解散后,员工仍然存在。
3、特点
- 弱拥有关系
- 部分对象生命周期独立
六、组合关系(Composition)
1、概念
组合表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系。在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。如下示例所示,房子没了,房间也就不存在了。
组合也是整体-部分关系,但更强:
部分对象不能脱离整体单独存在。
2、示例
👉 UML 表示:实心菱形 + 实线
classHouse{privateRoomroom;}房子没了,房间也就不存在了。
3、特点
- 强拥有关系
- 生命周期绑定
- 更符合封装原则
七、继承关系(Inheritance)
1、概念
继承关系是对象之间耦合度最大的一种关系,是父类与子类之间的关系,是一种继承关系。如下示例的类图,猫和狗继承了了动物的吃的方法。
继承表示:
一种“is-a”(是一个)的关系。
子类可以复用父类的属性和行为。
2、示例
👉 UML 表示:空心三角形 + 实线
classAnimal{voideat(){}}classDogextendsAnimal{}classCatextendsAnimal{}3、特点
- 强耦合
- 破坏封装风险
- 应慎用,优先考虑组合
八、实现关系(Implementation)
1、概念
实现关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。如下示例的类图,汽车和飞机实现了交通工具。
实现关系表示:
类对接口的实现,是一种“can-do”的关系。
2、示例
👉 UML 表示:空心三角形 + 虚线
interfaceVehicle{voidmove();}classCarimplementsVehicle{publicvoidmove(){}}classPlaneimplementsVehicle{publicvoidmove(){}}3、特点
- 面向接口编程的核心
- 解耦具体实现
- 有利于扩展和测试
九、关系强度对比总结
| 关系类型 | 强度 | 生命周期绑定 | 常见关键词 |
|---|---|---|---|
| 依赖 | ⭐ | 否 | use |
| 关联 | ⭐⭐ | 否 | know |
| 聚合 | ⭐⭐⭐ | 否 | has-a |
| 组合 | ⭐⭐⭐⭐ | 是 | owns-a |
| 继承 | ⭐⭐⭐⭐⭐ | 是 | is-a |
| 实现 | ⭐⭐⭐⭐ | 是 | can-do |
参考资料
黑马程序员 - bilibili.com
类和类之间的关系_类与类之间的关系-CSDN博客