认识 UML 类关系——依赖、关联、聚合、组合、泛化


在学习面向对象设计时,类关系涉及依赖、关联、聚合、组合和泛化这五种关系,耦合度依次递增。关于耦合度,可以简单地理解为当一个类发生变更时,对其他类造成的影响程度,影响越小则耦合度越弱,影响越大耦合度越强。

下面根据个人理解,尝试讲解这五种类关系。以 C++ 给出示例代码。

1.依赖(Dependency)

依赖关系使用虚线加箭头表示,如下图所示:

这里写图片描述

学生在学习生活中经常使用电脑,于是对电脑产生了依赖。依赖关系是五种关系中耦合最小的一种关系。类A要完成某个功能引用了类B,则类A依赖类B。依赖在代码中主要体现为类A的某个成员函数的返回值、形参、局部变量或静态方法的调用,则表示类A引用了类B

以 Student 类和 Computer 类为例,示例代码如下:

class Computer {
public:
	static void start(){
		cout<<"电脑正在启动"<<endl;
	} 
};

class Student {
public:
	//返回值构成依赖
	Computer& program();
	//形参构成依赖
	void program(Computer&);
	void playGame() {
		//局部变量构成依赖
		Computer* computer=new Computer;
		...
		//静态方法调用构成依赖
		Computer::star();
	}
};

2.关联(Association)

关联关系使用实线加箭头表示,类之间的关系比依赖要强。学生与老师是关联的,学生可以不用电脑,但是学生不能没有老师。如下图所示:

这里写图片描述

关联与依赖的相似之处:

关联暗示了依赖,二者都用来表示无法用聚合和组合表示的关系。

关联与依赖的区别:

(1)发生依赖关系的两个类都不会增加属性。其中的一个类作为另一个类的方法的参数或者返回值,或者是某个方法的变量而已。发生关联关系的两个类,类A成为类B的属性,而属性是一种更为紧密的耦合,更为长久的持有关系。

在代码中的表现如下:

class Teacher;
class Student {
public:
	Teacher teacher;  //成员变量
	void study();
}	

(2)从关系的生命周期来看,依赖关系是仅当类的方法被调用时而产生,伴随着方法的结束而结束。关联关系当类实例化的时候产生,当类对象销毁的时候关系结束。相比依赖,关联关系的生存期更长。

关联关系有单向关联、双向关联、自身关联、多维关联等,其中后三个可以不加箭头。

单向关联:

这里写图片描述

双向关联:

这里写图片描述

自身关联:

这里写图片描述

多维关联:

这里写图片描述

3.聚合(Aggregation)

聚合关系使用实线加空心菱形表示。聚合用来表示集体与个体之间的关联关系。

例如班级与学生之间存在聚合关系,类图表示如下:

这里写图片描述
聚合关系在代码上与关联关系表现一致,类 Student 将成为类 Classes 的成员变量。代码如下:

class Student;
class Classes {
public:
    Student* student; 
	Classes(Student* stu):student(stu) {}
};

4.组合(Composition)

组合(又叫复合)关系使用实线加实心菱形表示,用来表示个体与组成部分之间的关联关系。

例如学生与心脏之间存在复合关系,类图表示如下:

这里写图片描述
组合关系在代码上与关联关系表现一致,类 Heart 将成为类 Student 的成员变量。代码如下:

class Heart;
class Student {
public:
    Heart* heart; 
	Student() {
		heart=new Heart;
	}
	~Student() {
		delete heart;
	}
};

聚合与组合的对比:

(1)聚合关系没有组合紧密。

学生不会因为班级的解散而无法存在,聚合关系的类具有不同的生命周期;而学生如果没有心脏将无法存活,组合关系的类具有相同的生命周期。

这个从构造函数可以看出。聚合类的构造函数中包含另一个类的实例作为参数,因为构造函数中传递另一个类的实例,因此学生可以脱离班级体独立存在。组合类的构造函数包含另一个类的实例化。因为在构造函数中进行实例化,因此两者紧密耦合在一起,同生同灭,学生不能脱离心脏而存在。

(2)信息的封装性不同。

在聚合关系中,客户端可以同时了解 Classes 类和 Student 类,因为他们是独立的。

在组合关系中,客户端只认识 Student 类,根本不知道 Heart 类的存在,因为心脏类被严密地封装在学生类中。

理解聚合与组合的区别,主要在于聚合的成员可独立,组合的成员必须依赖于整体才有意义。

5.泛化(Generalization)

泛化是学术名称,通俗来讲,泛化指的是类与类之间的继承关系和类与接口之间的实现关系。

继承关系使用直线加空心三角形表示。类图结构如下:
这里写图片描述
类接口的实现关系使用虚线加空心三角形表示。类图结构如下:
这里写图片描述

6.小结

依赖、关联、聚合、组合与泛化代表类与类之间的耦合度依次递增。依赖实际上是一种比较弱的关联,聚合是一种比较强的关联,组合是一种更强的关联,泛化则是最强的关联,所以笼统的来区分的话,实际上这五种关系都是关联关系。

依赖关系比较好区分,它是耦合度最弱的一种,在编码中表现为类成员函数的局部变量、形参、返回值或对静态方法的调用。关联、聚合与组合在编码形式上都以类成员变量的形式来表示,所以只给出一段代码我们很难判断出是关联、聚合还是组合关系,我们需要从上下文语境中来判别。关联表示类之间存在联系,不存在集体与个体、个体与组成部分之间的关系。聚合表示类之间存在集体与个体的关系。组合表示个体与组成部分之间的关系。

依赖、关联、聚合与组合是逻辑上的关联,泛化是物理上的关联。物理上的关联指的是类体的耦合,所以类间耦合性最强。


参考文献

认识UML中类之间的依赖、关联、聚合、组合、泛化的关系
UML类关系(依赖,关联,聚合,组合的区别)
谈一谈自己对依赖、关联、聚合和组合之间区别的理解

  • 155
    点赞
  • 406
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
内容简介   本书通过引用UML规格书里的图例和定义详细介绍了UML的特色和发展历史,六UML图,元模型的说明,并且以StarUML为示范,讲解UML,工具如何落实UML概念,还介绍了活动图、控制节点、交互图、生命线、用例图等内容。   本书可作为高等院校计算机专业的教材和参考书,也可作为各希望了解UML的人员的参考书。 目录 前言 第1章 UML概述 1.1 语言与方法 1.2 图形语言 1.3 国际标准 1.4 面向对象 第2章 六UML图 2.1 图 2.1.1 2.1.2 可见性 2.1.3 关联 2.1.4 多重性 2.1.5 聚合组合 2.1.6 泛化 2.1.7 依赖 2.1.8 接口 2.1.9 注释 2.2 对象图 2.3 包图 2.3.1 包 2.3.2 元素导入 2.3.3 包导入 2.3.4 包合并 2.4 活动图 2.4.1 动作与控制流 2.4.2 对象节点与对象流 2.4.3 活动参数节点 2.4.4 引脚 2.4.5 起点与终点 2.4.6 合并 2.4.7 判断 2.5 序列图 2.5.1 交互 2.5.2 生命线 2.5.3 执行发生 2.5.4 消息 2.5.5 终止 2.5.6 一般次序 2.5.7 状态不变式 2.6 用例图 2.6.1 用例与执行者 2.6.2 包含关系 2.6.3 扩展关系 2.6.4 扩展点 第3章 图(一) 3.1 根基 3.1.1 元素 3.1.2 关系 3.1.3 有向关系 3.1.4.注释 3.2 名称空间 3.2.1 具名元素 3.2.2 名称空间 3.2.3 可见性种 3.2.4 装包元素 3.2.5 元素导入 3.2.6 包导入 3.3 多重性 3.3.1 多重性元素 3.3.2 型与型元素 3.4 表达式 3.4.1 值规格 3.4.2 表达式 3.4.3 不透明表达式 3.4.4 文字规格 3.4.5 实例值 3.5 约束 第4章 图(二) 4.1 实例 4.1.1 实例规格 4.1.2 槽 4.2 元 4.2.1 定义 4.2.2 泛化 4.2.3 可重定义元素 4.3 特征 4.3.1 定义 4.3.2 结构特征 4.3.3 行为特征 4.3.4 参数 4.3.5 参数方向种 4.4 操作 4.5 4.5.1 定义 4.5.2 性质 4.5.3 关联 4.5.4 聚合 第5章 图(三) 5.1 数据型 5.1.1 定义 5.1.2 基本型 5.1.3 枚举与枚举文字 5.2 包 5.2.1 定义 5.2.2 包合并 5.3 依赖 5.3.1 依赖与具名元素 5.3.2 使用关系 5.3.3 许可 5.3.4 抽象 5.3.5 实现 5.3.6 替代和元 5.4 接口 5.4.1 实现和行为元 5.4.2 接口定义 第6章 活动图 6.1 流程 6.1.1 活动节点与活动边 6.1.2 控制流 6.1.3 对象流 6.2 节点 6.2.1 活动 6.2.2 执行节点与动作 6.2.3 对象节点 6.2.4.活动参数节点 6.3 动作 6.3.1 引脚 6.3.2 输出引脚与输入引脚 6.3.3 值引脚 6.4 控制节点 6.4.1 定义 6.4.2 起始节点 6.4 _3终止节点与活动终点 6.4.4 合并节点 6.4.5 判断节点 第7章 交互图 7.1 交互 7.2 消息 7.2.1 消息与消息端 7.2.2 消息种与消息性质 7.2.3 事件发生与执行发生 7.2.4 一般次序 7.3 生命线 7.3.1 定义 7.3.2 状态不变式 7.3.3 终止 第8章 用例图 8.1 用例与元 8.2 关联泛化 8.3 执行者 8.4 包含关系 8.5 扩展关系 8.6 扩展点 第9章 杂项 9.1 基本型 9.2 UML图 9.2.1 图框 9.2.2 13图 9.3 共同行为 9.3.1 行为 9.3.2 行为元 9.3.3 活动 9.3.4 不透明表达式 9.4 构造型 9.4.1 辅助与焦点一 9.4.2 元 9.4.3 型与实现 9.4.4 工具 9.4.5 派生 9.4.6 精化 9.4.7 追踪 9.4.8 实例 9.4.9 创建 9.4.10 调用 9.4.11 发送 9.4.12 责任 9.4.13 创建 9.4.14 销毁 9.4.15 框架 9.4.16 模型库 9.4.17 实现 9.4.18 建造组件 9.4.19 脚本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值