UML 把类之间分为以下五种关系
- 关联:类A和类B的实列之间存在特定的对应关系
- 依赖:类A访问类B提供的服务
- 聚集:类A为整体类,类B为局部类,类A的对象由类B的对象组合而成
- 泛化:类A继承类B
- 实现:类A实现了B接口
1.1 关联
关联指的是类之间的特定对应关系,在UML中用带实线的箭头表示。按照类之间的数量对比,关联可分为以下三种:
- 一对一关联:例如假定个家庭教师只教一个学生, 一个学生只有一个家庭教师,那么家庭教师和学生之间是一对一 关联。
- 一对多关联:例如假定一个足球队员只能加入一一个球队, 一个球队可以包含多个队员,那么球队和队员之间是一对多关联。
- 多对多关联:例如假定一个足球队员可以加入多个球队,一 个球队可以包含多个队员,那么球队和队员之间是多对多关联。
例如,客户Customer与订单Order之间也存在一对多 的关联关系,一个 客户有多个订单,而一个订单只能属于一个客户,如图显示了它们的类框图。如果类A与类B关联,那么类A中会包含类B类型的属性。例如,在Order类中定义了Customer类型的属性:
以上代码建立了从Order类到Customer类的关联。同样,也可以建立Customer类到Order类的关联,由于一个Customer对象会对应多个Order对象,因此应该在Customer类中定义一个集合,来存放客户发出的所有订单。Customer类的定义如下:
关联还可以分为单向关联和双向关联:
- 单项关联:仅仅建立从Order到Customer的多对一关联,即仅仅在Order类中定义customer属性,或者仅仅建立从Customer到Order的一对多关联,即仅仅在Customer类中定义order集合属性。
- 双向关联:即建立从Order到Customer的多对一关联,又建立从Customer到Order的一对多关联
1.2 依赖
依赖指的是类之间的调用关系,在UML中用带虚线的箭头表示。如果类A访问类B的属性和方法,或者类A负责实例化类B,那么可以说类A依赖类B。和关联关系不同,无须在类A中定义类B类型的属性。列如Panel与Shape类之间存在依赖关系,因为Panel类会调用Shape类会调用Shape类的draw()方法。如图显示了Panel类与Shape类之间的依赖关系。
Panel类依赖Shape类
1.3 聚集(Aggregation)
聚集指的是整体与部分之间的关系,在UML中用带实线的菱形箭头表示。列如,台灯和灯泡之间的就是聚集关系,如图所示。
当ReadingLamp类由Blub类和Circuit类聚集而成时,在ReadingLamp类中应该包含Blub和Circuit类型的成员变量:
聚集关系还可以分为两种类型:
- 被聚集的子系统允许被拆卸和替换,这是普通聚集关系。例如,台灯和灯泡就是这种关系:此外,台式计算机上的大部分组件,如鼠标、打印机、声卡和网卡等,也是允许拆卸和替换的。
- 被聚集的子系统不允许被拆卸和替换,这种聚集关系也称为强聚集关系,或者叫组成关系。例如,台灯和它的电源线路就是这种关系:此外,有些计算机把显示卡、声卡和网卡集成到主板上,不允许拆卸,在这种情况下,计算机与显示卡、声卡和网卡之间就是强聚集关系。
1.4 泛化(Generalization)
泛化指的是类之间的继承关系,在UML中用带实线的三角形箭头表示。例如长方形Rectangle,圆形Circle和直线Line都继承Shape类,如图所示为他们的类框图。
Circle类,Line类和Rectangle类与Shape类之间的继承关系
1.5 实现(Realization)
实现指的是类与接口之间的关系,在UML中用虚线的三角形箭头所示,这里的接口指的是接口类型,接口名字用斜体字表示,接口中的方法都是抽象方法,也采用斜体字表示。例如以图所示的玻璃Glass类实现了Transparency接口。
Glass 类实现Transparency接口
1.6 区分依赖,关联和聚集关系
在建立对象模型时,很容易把依赖,关联和聚集关系混交。当对象A 和对象B 之间存在依赖,关联或聚集关系时,当对象A 都有可能调用对象B 的方法,这是三种关系之间的相同之处,除此之外,他们有着不同的特征。
- 依赖关系的特征
对于两个相对独立的系统,当一个系统负责构造另一个系统的实例,或者依赖另一个系统的服务时,这两个系统之间主要体现为依赖关系。例如,生产零件的机器和零件,机器负责构造零件对象:充电电池和充电器,充电电池通过充电器来充电:自行车Bicycle和打气筒Pump,自行车通过打气筒来充气。如图所示为Bicycle类与Pump类的类框图。
Bicycle类与Pump类之间的依赖关系
Bicycle类和Pump类之间的时依赖关系,在Bicycle中无须定义Pump类型的变量。Bicycle类的定义如下:
在现实生活中,通常不会为某一辆 自行车配备专门的打气筒,而是在需要充气的时候,从附近某个修车棚里借个打气简打气。在程序代码中,表现为Bicycle类的expand()方法有个Pump类型的参数。以下程序代码表示某一辆自行车先后到修车棚里充气:
- 关联关系的特征
对于两个相对独立的系统,当一个系统的实例与另一个系统的一些特定实例存在固定的对应关系时,这两个系统之间为关联关系。例如,客户和订单,每个订单对应特定的客户,每个客户对应一些特定的订单:公司和员工,每个公司对应一些特定的员工,每个员工对应一个特定的公司;自行车和主人,每辆自行车属于特定的主人,每个主人有特定的自行车,如图显示了主人和自行车的关联关系。而充电电池和充电器之间就不存在固定的对应关系,同样白行车和打气筒之间也不存在固定的对应关系。
主人和自行车的关联关系
Person 类与Bicycle 类之间存在关联关系,这意味着在Person类中需要定义一个Bicyele 类型的成员变量。以下是Person类的定义:
在现实生活中,当你骑自行车去上班时,只要从家里推出自己的自行车就能上路了,不像给自行车打气那样,在需要打气时,还要四处去找修车棚。因此,在Peson类的goToWork0方法中,调用自身的bicyele 对象的rum0方法。假如goToWork0方法采用以下定义方式:
那就好比去上班前,还要先四处去借一辆自行车, 然后才能去上班。
- 聚集关系的特征
当系统A被加入到系统B中,成为系统B的组成部分时,系统B和系统A之间为聚集关系。例如,自行车和它的响铃、龙头、轮胎、钢圈及刹车装置就是聚集关系,因为响铃是自行车的组成部分。而人和自行车不是聚集关系,因为人不是由自行车组成的,如果一定要研究人的组成,那么他应该由头、躯干和四肢等组成。再例如书包和书,以及文具是关联关系,而书包和书包上的拉链及带子等是聚集关系。由此可见,可以根据语义来区分关联关系和聚集关系。
聚集关系和关联关系的区别还表现在以下方面:
- 对于具有关联关系的两个对象,多数情况下,两者有独立的生命周期。比如自行车和他的主人,自行车不存在了以后,它的主人依然存在:反之亦然。但在个别情况下,一方 会制约另方的生 命周期。比如客户和订单,当客户不存在时,它的订单也就失去了存在的意义。
●对于具有聚集关系(尤其是强聚集关系)的两个对象,整体对象会制约它的组成对象的生命周期。部分类的对象不能单独存在,它的生命周期依赖于整体类的对象的生命周期,当整体消失时,部分也就随之消失。比如小王的自行车被偷了,那么自行车的所有组件也不存在了,除非小王事先碰巧把一些可拆卸的组件(比如车铃和坐垫)拆了下来。
不过,在用程序代码来表示关联关系和聚集关系时,两者比较相似。如图所示为自行车Bicyele与响铃Bell的聚集关系。
自行车和响铃的聚集关系
Bicycle类的源程序
在Bicycle类中定义了Bell类型的成员变量,Bicycle类利用自身的bell成员变量来发出铃声,这和在Person类中定义了Bicycle类型的成员变量,Person类利用自身的bicycle成员变量去上班很相似。