在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization), 关联(Association), 聚合(Aggregation), 组合(Composition), 依赖(Dependency)
1. 泛化(Generalization)
【泛化关系】:是一种继承关系, 表示一般与特殊的关系, 它指定了子类如何特化父类的所有特征和行为. 例如:老虎是动物的一种, 即有老虎的特性也有动物的共性.
【箭头指向】:带三角箭头的实线,箭头指向父类
2. 实现(Realization)
【实现关系】:是一种类与接口的关系, 表示类是接口所有特征和行为的实现.
【箭头指向】:带三角箭头的虚线,箭头指向接口
3. 关联(Association)
【关联关系】:是一种拥有的关系, 它使一个类知道另一个类的属性和方法;如:老师与学生,丈夫与妻子
关联可以是双向的,也可以是单向的。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。
【代码体现】:成员变量
【箭头及指向】:带普通箭头的实心线,指向被拥有者
上图中,老师与学生是双向关联,老师有多名学生,学生也可能有多名老师。但学生与某课程间的关系为单向关联,一名学生可能要上多门课程,课程是个抽象的东西他不拥有学生。
上图为自身关联:
4. 聚合(Aggregation)
【聚合关系】:是整体与部分的关系, 且部分可以离开整体而单独存在. 如车和轮胎是整体和部分的关系, 轮胎离开车仍然可以存在.
聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。
【代码体现】:成员变量
【箭头及指向】:带空心菱形的实心线,菱形指向整体
5. 组合(Composition)
【组合关系】:是整体与部分的关系, 但部分不能离开整体而单独存在. 如公司和部门是整体和部分的关系, 没有公司就不存在部门.
【代码体现】:成员变量
【箭头及指向】:带实心菱形的实线,菱形指向整体
6. 依赖(Dependency)
【依赖关系】:是一种使用的关系, 即一个类的实现需要另一个类的协助, 所以要尽量不使用双向的互相依赖.
【代码表现】:局部变量、方法的参数或者对静态方法的调用
【箭头及指向】:带箭头的虚线,指向被使用者
各种关系的强弱顺序:
泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖
下面这张UML图,比较形象地展示了各种类图关系:
聚合关系图:
组合关系图:
聚合关系的类里含有另一个类作为参数。
雁群类(GooseGroup)的构造函数中要用到大雁(Goose)作为参数把值传进来 大雁类(Goose)可以脱离雁群类而独立存在 。
组合关系的类里含有另一个类的实例化 。
大雁类(Goose)在实例化之前 一定要先实例化翅膀类(Wings) 两个类紧密耦合在一起 它们有相同的生命周期 翅膀类(Wings)不可以脱离大雁类(Goose)而独立存在 。
信息的封装性不同 。
在聚合关系中,客户端可以同时了解雁群类和大雁类,因为他们都是独立的 。
而在组合关系中,客户端只认识大雁类,根本就不知道翅膀类的存在,因为翅膀类被严密的封装在大雁类中。
聚合与组合
(1)聚合与组合都是一种结合关系,只是额外具有整体-部分的意涵。
(2)部件的生命周期不同
聚合关系中,整件不会拥有部件的生命周期,所以整件删除时,部件不会被删除。再者,多个整件可以共享同一个部件。
组合关系中,整件拥有部件的生命周期,所以整件删除时,部件一定会跟着删除。而且,多个整件不可以同时间共享同一个部件。
(3)聚合关系是“has-a”关系,组合关系是“contains-a”关系。
关联和聚合
(1)表现在代码层面,和关联关系是一致的,只能从语义级别来区分。
(2)关联和聚合的区别主要在语义上,关联的两个对象之间一般是平等的,例如你是我的朋友,聚合则一般不是平等的。
(3)关联是一种结构化的关系,指一种对象和另一种对象有联系。
(4)关联和聚合是视问题域而定的,例如在关心汽车的领域里,轮胎是一定要组合在汽车类中的,因为它离开了汽车就没有意义了。但是在卖轮胎的店铺业务里,就算轮胎离开了汽车,它也是有意义的,这就可以用聚合了。
关联和依赖
(1)关联关系中,体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比如我和我的朋友;这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的。
(2)依赖关系中,可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是B类的变化会影响到A。
综合比较
这几种关系都是语义级别的,所以从代码层面并不能完全区分各种关系;但总的来说,后几种关系所表现的强弱程度依次为:
组合>聚合>关联>依赖;