代码改变世界

设计模式基础:类及类关系的UML表示

2009-10-26 17:00  宗哥  阅读(4688)  评论(1编辑  收藏  举报

UML中,类关系分为这几种,泛化(generalization), 实现(realization),依赖(Dependency),关联(associate),聚合(aggregation),(composition)下面分别是UML实现及C#中的代码表现。

泛化(generalization)

      泛化也称作特化(specialization),用来表示一个更一般和更特殊的分类器之间的关系,从面向对象的角度来看,他表达的是类和类之间的继承(inheritance)关系。

例如:Person(人)继承了Organism(生物)类, Organism是更一般的分类器,Person是更特殊的分类器。

clip_image001clip_image003

        注意,泛化在语义上理解为更特殊的分类器 is kind of更一般的关系,本例我们可以理解人是生物的一种或者是一种生物。记住这点很重要。

实现(realization)

        是指特殊化的分类器和接口之间的一种关系,从面向对象的角度来看,他表达的是分类器遵守并实现接口的契约(Contract)。

例如:奇瑞公司要生产一款轿车,由于产能原因发动起部分决定采用不同厂家的发动机,他只要规范这个发动机的一些参数可以。BmwEngine(宝马发动机)和AndiEngion(奥迪发动机)实现了Engine的契约,便可以被采用。

clip_image005clip_image007

        接口表示 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。

clip_image009

clip_image011clip_image013

        依赖(Dependency)关系语义上是比较弱的一种关系模型,通常在以下情况我们认为A依赖于B:

                1. A中的方法中有B类型的参数

                2. A方法中实例化B或者调用了B的静态方法

关联(associate)

        关联我们分单项管理和双向关联。单相关联表示两个类是相关的,但是只有一个类知道这种联系的存在,双向关联两个类彼此知道它们间的联系。

双向关联的例子:FeedIn(订单)类和Order (订单)类:

clip_image015

clip_image017

类FeedIn的代码

clip_image019

        类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)类:

clip_image021

clip_image023

                Order Report的部分代码

clip_image025

          注意其箭头编号和Order中代码,可以看出,Order不知道Order Report(订单报表)的存在。

C#依赖和关联的比较

        在C#中,关联的类通常体现在类的成员变量,表示一种相对固定长期的关系,而依赖关系通常体现在局部变量,表示一种相对偶然,临时的关系。

聚合(aggregation)

        聚合也是一种关联,但是对于关联来讲,关联的双方没有明显的主次关系,例如 FeedIn(入库单)类和订单(Order)类,Order Report(订单报表)类和订单(Order)类等等,聚合在聚集中,则有主次之分,“主”的一方只能有一个。

        例如Order(订单)和 OrderDetail(订单明细),

clip_image027

clip_image029 Order的部分代码

clip_image031

                                                        Order Detail的部分代码

        聚集关系和关联关系的区别还表现在以下方面:

(1) 对于具有关联关系的两个对象,多数情况下,两者有独立的生命周期。FeedIn(入库单)类和订单(Order)类,。FeedIn(入库单)的销毁不会影响订单(Order);反之亦然。

(2) 对于具有聚集关系(尤其是强聚集关系)的两个对象,整体对象会制约它的组成对象的生命周期。部分类的对象不能单独存在,它的生命周期依赖于整体类的对象的生命周期,当整体消失,部分也就随之消失。例如Order(订单)和 OrderDetail(订单明细),不过,有的设计者也允许单独的OrderDetail存在,这有点类似我们说的“数据岛”之类的问题。

        不过,在C#中表示关联关系和聚集关系时,两者比较相似,都是作为成员变量存在。

组合(composition)

        关联(associate)关系在设计中一般体现为聚合(aggregation)和组合(composition)关系,组合和聚合相似,但表示一种更强烈的组合语义关系:

例如Person(人)和 Head(头),

clip_image033

clip_image035

Person(头)类的部分代码

clip_image037

                        Head(头)类的部分代码

UML图及关系总结:

泛化(继承):表示一般与特殊的关系,用一条实线加空心箭头来表示;

实现:表示类与接口的关系,用一条虚线加空心箭头来表示;
关联:连接模型元素及链接实例,用一条实线来表示;

依赖:表示一个元素以某种方式依赖于另一个元素,用一条虚线加箭头来表示;

聚集:表示整体与部分的关系,用一条实线加空心菱形来表示;

组成:表示整体与部分的有一关系,用一条实线加实心菱形来表示;

;