UML类图以及常见类关系图解
程序员文章站
2022-03-04 13:17:45
最近查询了类图中的常见关系,网上有不少或详细或简略的解释,大部分都是一张图被来来回回的复制粘贴,我借这个文档重新梳理一下概念和类关系。文章目录基本概念类关系泛化 Generalization实现 Realization依赖 Dependency关联 Association聚合 Aggregation组合 Composition一图汇总参考基本概念类图(Class Diagram): 类图是面......
最近查询了类图中的常见关系,网上有不少或详细或简略的解释,大部分都是一张图被来来回回的复制粘贴,我借这个文档重新梳理一下概念和类关系。
文章目录
基本概念
类图(Class Diagram): 类图是面向对象系统建模中最常用和最重要的图,是定义其它图的基础。类图主要是用来显示系统中的类、接口以及它们之间的静态结构和关系的一种静态模型。
类图的3个基本组件:类名、属性、方法。
在画类图的时候,常见的类关系有:泛化(Generalization)、实现(Realization)、依赖(Dependency)和关联(Association)。其中关联又分为一般关联关系和聚合关系(Aggregation),组合关系(Composition)。下面我们结合实例理解这些关系。
关系名 | 英文 | 关系描述 | 标识 |
---|---|---|---|
泛化 | Generalization | 表示is-a的关系,子类继承父类 | 带三角箭头的实线 |
实现 | Realization | 表示接口和实现的关系 | 带三角箭头的虚线 |
依赖 | Dependency | 表示use-a的关系,临时性的关联 | 带箭头的虚线 |
关联 | Association | 表示对象之间的引用关系 | 带箭头的实线 |
聚合 | Aggregation | 表示has-a的关系,是一种不稳定的包含关系 | 带空心菱形的实线 |
组合 | Composition | 表示contains-a的关系,是一种强烈的包含关系 | 带实心菱形的实线 |
关系的强弱顺序:
泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖
类关系
泛化 Generalization
- 关系描述:表示is-a的关系,子类继承父类。
- 箭头指向:子类指向父类
- 代码实现:
public class Bird extends Animal {
}
- 思考:
- 泛化和继承是一回事吗?
继承和泛化都表示的是子类和父类的关系,但也有区别,只是看问题的角度不同,子类继承父类,父类泛化子类。 - 为什么建议多用组合少用继承?
类继承是在编译时静态定义,子类继承可以方便的改变父类的实现,同时也有不足之处:1. 因为继承在编译时刻就定义了,所以无法在运行时改变父类继承的实现。2. 父类通常定义了子类的部分行为,父类的任何改变都可以影响子类的行为,如果继承下来的实现不适合子类,则父类必须重写或被其他更适合的替换,不论哪种都要考虑对继承于父类的其它子类的影响。这种强依赖关系限制了灵活性并最终限制了复用性。
组合是通过获取对其他对象的引用而在运行时刻动态定义的,由于组合要求具有良好定义的接口,而且,对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。
- 泛化和继承是一回事吗?
实现 Realization
- 关系描述:表示接口和实现的关系。
- 箭头指向:实现类指向接口
- 代码实现:
public class Bird implements IFly {
}
- 思考:
接口是一种特殊的抽象类,这种抽象类中值包含常量和方法的定义,而没有变量和方法的实现。
依赖 Dependency
- 关系描述:类之间最弱的一种关联方式,是临时性的关联,表示Use a。代码中一般指由局部变量、函数参数、返回值建立的对于其他对象的调用关系。一个类调用被依赖类中的某些方法而得以完成这个类的一些职责。
- 箭头指向:使用类指向被依赖类
- 代码实现:
public abstract class Animal{
}
public class Air{
}
public class Water{
}
- 思考:
- 依赖关系到底是如何体现的呢?
- Air、Water类是全局的,则Animal类可以调用它
- Air、Water类是Animal类的方法中的局部变量
- Air、Water类是作为Animal类中方法的参数或者返回值
- 依赖关系到底是如何体现的呢?
public class Animal {
public void Grow() {
Air air = new Air();
Water water = new Water();
}
public Water Drink(Water water) {
}
}
关联 Association
- 关系描述:表示对象之间一种引用关系,比如客户类与订单类之间的关系。这种关系通常使用类的属性表达。关联分为一般关联、聚合关联与组合关联。一般关联又可以分两类:单向关联和双向关联。
- 箭头指向:引用类指向被引用类
- 代码实现:
public class Water {
public Climate climate;
public Water() {}
}
- 思考:
- 其它关联的例子?
上面用水和气候作为一个例子,作为引用关系理解起来比较弱。这里再举一个例子,比如学生与课程的双向关联关系,一个学生可以有选择多门课程,同时一门课有多名报名的学生。
- 依赖关联和关联关系的区别在哪里?
(1)从类属性定义角度看:
发生依赖关系的两个类都不会增加属性,其中的一个类作为另一个类的方法的参数、返回值,或者局部变量存在。
发生关联关系的两个类,其中的一个类称为另一个类的属性,而属性是一种更为紧密的耦合,更为长久的持有关系。
(2)从关系的生命周期角度看:
依赖关系是仅当类的方法被调用时而产生的,伴随着方法的结束而结束。
关联关系是当类实例化的时候即产生,当类对象销毁的时候,关系结束。相对依赖来说,关联关系的生命周期更长。
- 其它关联的例子?
聚合 Aggregation
- 关系描述:表示has-a的关系,是一种不稳定的包含关系。较强于一般关联,有整体与局部的关系,并且没有了整体,局部也可单独存在。如公司和员工的关系,公司包含员工,但如果公司倒闭,员工依然可以换家公司。再比如班级与学生的关系,动物中雁群和大雁的关系,大部分例子都是群体和个体的关系。
- 箭头指向:带空心菱形的实线,菱形指向整体,箭头指向个体
- 代码实现:
public class WildGooseGroup {
public List<WildGoose> wildGooses;
public WildGooseGroup (List<WildGoose> wildGooses) {
this.wildGooses = wildGooses;
}
}
- 思考:
有的用汽车和轮胎的关系作为聚合的例子,这里判断这种关系是聚合还是组合的关键在于对于部分概念的定位。如果系统服务于汽车使用人,定位轮胎只能作为汽车的一部分出现,那么轮胎就是汽车不可分割的一部分,汽车和轮胎就是组合关系。如果系统服务于汽车制造商/修理厂,定位轮胎是汽车的一个部件,可以使用不同轮胎和汽车进行装配,那么轮胎就是可以独立于汽车存在,汽车和轮胎就是聚合关系。
在实现上,部分类都是作为整体类的一个属性进行关联。
组合 Composition
- 关系描述:表示contains-a的关系,是一种强烈的包含关系。组合类负责被组合类的生命周期。是一种更强的聚合关系。部分不能脱离整体存在。如公司和部门的关系,没有了公司,部门也不能存在了。
- 箭头指向:带实心菱形的实线,菱形指向整体,箭头指向部分
- 代码实现:
public class WildGoose extends Bird {
private List<Wing> wings;
public WildGoose () {
wings = new ArrayList<>();
}
}
- 思考:
- 组合关联和聚合关联的区别在哪里?
(1)构造函数不同
聚合类的构造函数中包含了另外一个类作为参数,WildGooseGroup的构造函数中用到WildGoose作为参数传递进来,WildGoose可以脱离WildGooseGroup独立存在。
组合类的构造函数中包含了一个类的实例化,表明大雁类在实例化之前,一定要先实例化Wing类,这两个类紧密的耦合在一起,同生共灭。Wing类是不可以脱离大雁类独立存在的。
(2)信息的封装性不同
聚合关系中,客户端可以同时了解WildGooseGroup和大雁类,因为他们是独立的;
组合关系中,客户端只认识大雁类,不知道Wing类的存在,因为Wing类被封装在大雁类中。
- 组合关联和聚合关联的区别在哪里?
一图汇总
上面的6类关系汇总在一张图上
参考
UML类图与类的关系详解 - uml.org.cn
UML类图 - w3cschool
UML类图几种关系的总结 - tianhai110 csdn blog
UML类图五种关系与代码的对应关系 - Zhangxichao100 csdn blog
本文地址:https://blog.csdn.net/u011798638/article/details/85960320