UML中,类关系分为这几种,泛化(generalization), 实现(realization),依赖(Dependency),关联(associate),聚合(aggregation),(composition)下面分别是UML实现及C#中的代码表现。
泛化(generalization)
泛化也称作特化(specialization),用来表示一个更一般和更特殊的分类器之间的关系,从面向对象的角度来看,他表达的是类和类之间的继承(inheritance)关系。
例如:Person(人)继承了Organism(生物)类, Organism是更一般的分类器,Person是更特殊的分类器。
注意,泛化在语义上理解为更特殊的分类器 is kind of更一般的关系,本例我们可以理解人是生物的一种或者是一种生物。记住这点很重要。
实现(realization)
是指特殊化的分类器和接口之间的一种关系,从面向对象的角度来看,他表达的是分类器遵守并实现接口的契约(Contract)。
例如:奇瑞公司要生产一款轿车,由于产能原因发动起部分决定采用不同厂家的发动机,他只要规范这个发动机的一些参数可以。BmwEngine(宝马发动机)和AndiEngion(奥迪发动机)实现了Engine的契约,便可以被采用。
接口表示 I can do的一种概念,例如 BmwEngine(宝马引擎)完全可以做Engine(引擎)做的事情。
C#中 泛化(generalization)和实现(realization)的比较
我们不讨论语言层面抽象类 (abstract class) 和接口(Interface)的技术性差别。
在C#中,泛化我们主要指类和类的继承关系,表示is kind of的关系,当然如果一个接口继承了另外一个接口,我也主张把他划分为泛化,这符合is kind of的观点。实现主要指类和接口的关系,表示这个类完全实现了接口成员,I can do 。当然两者在C#实现上都是通过符合”:”实现,但是在语义上完全是两回事情,在UML关系图中识别也不一样。还要提醒你下,如果在C#中,你的类如果继承了一个类,同时实现了一或者多个接口,一定要把类写在所有接口的前面。
依赖(Dependency)
依赖关系是一种相对简单的关系,表示一个类会用到另外一个类,这个关系具有相对的偶然性。他表达的是参与关系的模型元素,并不会直接转化为程序代码(前文我们讲的泛化和实现都直接转化为程序代码了)。
例如 微软SqlHelper类和SqlConnetciont(Sql连接),可以看做SqlHelper依赖SqlConnetciont。
依赖(Dependency)关系语义上是比较弱的一种关系模型,通常在以下情况我们认为A依赖于B:
1. A中的方法中有B类型的参数
2. A方法中实例化B或者调用了B的静态方法
关联(associate)
关联我们分单项管理和双向关联。单相关联表示两个类是相关的,但是只有一个类知道这种联系的存在,双向关联两个类彼此知道它们间的联系。
双向关联的例子:FeedIn(订单)类和Order (订单)类:
类FeedIn的代码
类Order的部分代码
可以看出,Order类知道他的Feed In,FeedIn也知道他的Order。
注意其多重值的含义:
可能的多重值描述 |
|
表示 |
含义 |
0..1 |
0个或1个 |
1 |
只能1个 |
0..* |
0个或多个 |
* |
0个或多个 |
1..* |
1个或我个 |
3 |
只能3个 |
0..5 |
0到5个 |
5..15 |
5到15个 |
单项关联的例子:Order Report(订单报表)类和订单(Order)类:
Order Report的部分代码
注意其箭头编号和Order中代码,可以看出,Order不知道Order Report(订单报表)的存在。
C#依赖和关联的比较
在C#中,关联的类通常体现在类的成员变量,表示一种相对固定长期的关系,而依赖关系通常体现在局部变量,表示一种相对偶然,临时的关系。
聚合(aggregation)
聚合也是一种关联,但是对于关联来讲,关联的双方没有明显的主次关系,例如 FeedIn(入库单)类和订单(Order)类,Order Report(订单报表)类和订单(Order)类等等,聚合在聚集中,则有主次之分,“主”的一方只能有一个。
例如Order(订单)和 OrderDetail(订单明细),
Order Detail的部分代码
聚集关系和关联关系的区别还表现在以下方面:
(1) 对于具有关联关系的两个对象,多数情况下,两者有独立的生命周期。FeedIn(入库单)类和订单(Order)类,。FeedIn(入库单)的销毁不会影响订单(Order);反之亦然。
(2) 对于具有聚集关系(尤其是强聚集关系)的两个对象,整体对象会制约它的组成对象的生命周期。部分类的对象不能单独存在,它的生命周期依赖于整体类的对象的生命周期,当整体消失,部分也就随之消失。例如Order(订单)和 OrderDetail(订单明细),不过,有的设计者也允许单独的OrderDetail存在,这有点类似我们说的“数据岛”之类的问题。
不过,在C#中表示关联关系和聚集关系时,两者比较相似,都是作为成员变量存在。
组合(composition)
关联(associate)关系在设计中一般体现为聚合(aggregation)和组合(composition)关系,组合和聚合相似,但表示一种更强烈的组合语义关系:
例如Person(人)和 Head(头),
Person(头)类的部分代码
Head(头)类的部分代码
UML图及关系总结:
泛化(继承):表示一般与特殊的关系,用一条实线加空心箭头来表示;
实现:表示类与接口的关系,用一条虚线加空心箭头来表示;
关联:连接模型元素及链接实例,用一条实线来表示;
依赖:表示一个元素以某种方式依赖于另一个元素,用一条虚线加箭头来表示;
聚集:表示整体与部分的关系,用一条实线加空心菱形来表示;
组成:表示整体与部分的有一关系,用一条实线加实心菱形来表示;