今天我们来看UML基本构造块的还有一个要素——关系。
UML中有表示基本图示符号之间的关系,它们是:依赖(dependency)、泛化(generalization,也有的称继承)、实
现(realization)和关联(association),而关联又分为普通关联(common association)、聚合(aggregation,也有的称聚
集)和组合(composition)。
依赖(dependency)
依赖关系表示为一个类A使用还有一个类B。这样的使用关系是具有偶然性的、暂时性的、很弱的,可是类B的变化
会影响到类A,是use a关系。
表如今生活中,比方某人要过河,须要借用一条船。此时人与船之间的关系就是依赖。表如今代码层面假设类A
依赖于类B,那么类B能够是类A的局部变量,或类A方法的參数,或静态方法的调用。
图示:虚线加箭头(箭头指向的是被依赖的那一方)
举例:
说明:动物有几大特征,比方有新陈代谢。能生殖。而动物要有生命力,须要氧气、水以及食物等。也就是说,
动物依赖氧气和水。
他们之间是依赖关系(dependency)。用虚线加箭头来表示。
我们再来看一个代码层面上的样例:
说明:假设两个类有结构关系(关联关系),那么就不用依赖关系(两个事物一般都有这个关系)。
泛化(generalization)
泛化即继承关系。泛化是一种特殊/一般关系,特殊元素(子元素)的对象可替代一般元素(父元素)的对象。用这样的
方法。子元素共享了父元素的结构和行为。是is-a关系,详细表现为类与类的继承,接口与接口的继承。
泛化指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并能够添加它自己的新功
能的能力,继承是类与类或者接口与接口之间最常见的关系。在Java中此类关系通过keywordextends明白标识,在设
计时一般没有争议性。
图示:实线+空心三角
举例:
实现(realization)
实现是类元之前的语义关系,在该关系中一个类元描写叙述了还有一个类元保证实现的契约。
实现指的是一个class类实
现interface接口(能够是多个)的功能;实现是类与接口之间最常见的关系;在Java中此类关系通过keywordimplements
明白标识,在设计时一般没有争议性。
图示:虚线+空心箭头
举例:
关联(association)
关联描写叙述了两个或多个类之间的结构性关系。表示类与类之间的联接。它使一个类知道另一个类的属性和方法。
关联体现的是两个类、或者类与接口之间语义级别的一种强依赖关系,比方我和我的朋友;这样的关系比依赖更强、不
存在依赖关系的偶然性、关系也不是暂时性的,通常是长期性的。并且两方的关系通常是平等的、关联能够是单向、
双向的;表如今代码层面,假如类A关联了类B,则类B是类A的全局变量(注意是全局变量,再看看上面的依赖关系)。
大多数关联都是单向关联。这比較easy维护,关于关联,在生活中我们常会说,类A持有类B的引用。为被关联类B以
类属性的形式出如今关联类A中,也可能是关联类A引用了一个类型为被关联类B的全局变量。
(1)普通关联(common association)
1)Association name名称:用以描写叙述该关系的性质。
2)Role角色:当一个类处于关联的某一端时,该类就在这个关系中扮演了一个特定的角色;角色是关联中靠近它
的一端的类对另外一端的类呈现的职责。
3)Multiplicity多重性:关联角色的多重性是说明一个关联的实例中有多少个相互连接的对象。
图示:直线
举例:
(2)聚合(aggregation)
聚合关系是特殊的关联关系。是一种强的关联关系,他体现的是总体与部分关系,即has-a的关系。可是总体和
部分是能够分离的。注意。是能够分离的。他们能够具有各自的生命周期,部分能够属于多个总体对象,也能够为多
个总体对象共享;比方计算机CPU、公司与员工的关系等;表如今代码层面,和关联关系是一致的,仅仅能从语义级别
来区分。
普通关联关系的两个类处于同一层次上。是平级的,而聚合关系的两个类处于不同的层次,一个是总体,一个是
部分。
同一时候。是一种弱的“拥有”关系。体现的是A对象能够包括B对象,但B对象不是A对象的组成部分。详细表现为,
假设A由B聚合成,表现为A包括有B的全局对象,可是B对象能够不在A创建的时刻创建,这句话很有意义。它在代
码中通常体现成依赖注入的setter方法,即A对象能够随时创建B对象,再想想这不就体现了总体和部分是能够分离了
吗?创建总体的时候能够不创建部分。
图示:空心菱形+实线+箭头
举例:
(3)组合(Composition)
组合也是关联关系的一种特例,他体现的是一种contains-a(拥有)的关系,这样的关系比聚合更强,也称为强聚
合。它相同体现总体与部分间的关系,但此时总体与部分是不可分的,总体的生命周期结束也就意味着部分的生命周
期结束;比方你和你的大脑;表如今代码层面,和关联关系是一致的,仅仅能从语义级别来区分;表如今代码层面上,
假设A由B组成,那么A就包括B的全局变量,并在创建A的同一时候创建B,在代码上我们一般是使用构造函数进行实现。
也是依赖注入中构造函数的实现。
图示:实心菱形+实线+箭头
举例:
总结
最后,我们来总结一下。泛化和实现就不用多少了,大家都懂的,就是继承和实现接口。重点说下其他的吧,依
赖,ClassB体现为ClassA的局部变量,我想用就用,用了就有关系。不用就没关系。关联,ClassB体现为ClassA的
全局变量,无论你用不用。反正你知道我的存在了,持有了我的引用。聚合,是特殊的关联关系,用了就加强了关
系,不用还是我仅仅知道你的存在。聚合能够方便的持有多个类的引用。如使用List<>,所以当你发现有List<>等集合
是能够使用聚合来表示,比方观察者模式的结构。组合,体现最强关系,比方人出身了。必然也有头部吧,不然我真
无法想象这个世界了。
涵盖上述四种关系的一个类图:
解释:
1)Window类实现了AbstractWindow接口。
2)ConsoleWindow类和DialogBox类都继承(泛化)自Window类。
3)Window类依赖于Event类。也就是Window类会使用到Event类。
4)Dialog类和Control类互相关联。