我想聊一聊UML的几种关系,包括关联关系,聚合关系,组合关系,依赖关系。
在具体讨论之前我想先说一些废话,但又不得不说。由于自己曾经也因为这几种关系困惑过,所以我会以一种很容易理解的,简洁的方式来解释这几种关系,希望对正在寻觅的朋友们能有哪怕一点帮助,那么我的这篇文章也是有价值的,废话结束。
首先我们应当明白,这几种关系都是对现实世界中确实存在的关系的描述和概括。下面我会将这几种关系对应到现实世界中确实存在的一些关系,这么做是因为我不想空洞地,莫名其妙地讲理论,我想将抽象的东西具体化,方便大家理解。当大家理解之后还需进行总结和概括。
由于关联,聚合,组合是同一类关系,所以放在一起讲,并且按照我列出的顺序,关系的强度是递增的,稍后我将说明为什么。
关联:
在Java代码中表现为:
1 public class Person{ //The person who wears the clothes 2 private Colthes colthes; 3 }
首先设定几个对象:①人,②穿着衣服的人,③衣服。“人”的存在与否不受衣服的影响。组成因素当然也不包含“衣服”。但是在一些特定时间或环境下“人”这个类必须要持有“衣服”这个类,此时产生了“穿着衣服的人”这个类。而“ 穿着衣服的人 ”和“衣服”是关联关系,表现在程序中是“人”这个类持有“衣服”这个类的一个对象从而组成了“ 穿衣服的人 ”这个类。(这是由“穿衣服的人”到“衣服”的单向关联,关联关系也可以是双向的。)由于对于“人”和“ 穿衣服的人 ”来说后者是前者在特定时刻,特定条件下的转换,正因对特定条件和特定时刻的需求,所以关联关系较弱。 由此可见关联关系是不连续的,也有一定的偶然性和临时性,但是这种偶然和临时比依赖强,表现形式也不同。
聚合:
在Java代码中表现为:
1 public class Room { 2 private Wall wall; 3 }
设定对象:①房间,②墙。无论什么时刻“墙”都是房间的组成成分,所以聚合相对关联较强。但一堵“墙”可以同时参与构成两个房子,“墙”与“房子”是一对多的关系,也就是说组成整体的成分对象可以被共享(基于同一时刻的共享),既在同一时刻一个部分可共同参与组成多个整体。
组合:
在Java代码中表现为:
1 public interface Eye { 2 }
1 public class RightEye extends Eye { 2 }
1 public class LeftEye extends Eye { 2 }
1 public class Person1 { 2 private Eye leftEye; 3 private Eye rightEye; 4 }
设定对象:①人,②眼睛。无论什么时候“眼睛”都是“人”的组成成分,并且人和眼睛一一对应,一个“人”完全拥有具体的一对“眼睛”,并且完全拥有对这对眼睛的支配权(包括湮灭和转交)。在某个具体的时间点上这双眼睛只属于某一个具体的人。当整体湮灭的时候成分对象有两种结果:1.随整体湮灭,2.转交给其它整体。第二种情况是比较少见的。例如,一个人在活着的时候拥有一双确定的眼睛,湮灭后眼睛可以一起湮灭,也可以捐给别人(姚贝娜就这么做了)。但无论怎样,就眼睛来说同一时刻只能属于一个整体。所以在某一具体时刻整体的成份对象是不能被共享的。(部分可分时地去参与多个整体,例如一个人在活着的时候把自己的眼睛捐给了另一个人,一段时间后另一个人又把眼睛给了第三个人)。所以组合相对于聚合又更强。
到这里前三种关系解释完毕,下面说一说依赖。
依赖:
在Java代码中表现为:
1 public class Person { 2 public void Drive(Car car) { 3 4 } 5 6 public Car Create() { 7 return new Car(); 8 } 9 }
设定对象:①人,②车。设定行为:a人开车. b人造车。只有当人产生开车这个行为时对于人这个类来说才需要车这个类的对象,在程序中表现为人有一个函数是开车,而开车这个函数有一个参数是车的对象。人还可以有造车的行为,表现在程序中就是有一个函数,返回值是车。由此可见 依赖是一种临时的,不持久的,偶然的关联,对于类的存在完全没影响,只是行为,功能的需求,也就是说没有这种依赖,功能会欠缺。但不会影响到实物的性质。换句话说就是并不是谁一定离不开谁。
正是由于这四种关系存在种种差异,所以能被区分,又由于前三种存在共同特性所以可归结为一类,但通过差异和共性所区分的这四种关系在现实中确实存在,所以是合理的。我所做的仅仅是将差异和共性展现了出来。
——Edit by Ivenjow,Silence_w