设为首页 加入收藏

TOP

1.5 关于类图的约定
2013-10-07 15:19:11 来源: 作者: 【 】 浏览:58
Tags:1.5 关于 约定

1.5  关于类图的约定

本书使用UML(Unified Modeling Language)描述类之间的关系。虽然市面上多款UML建模与绘制工具都宣称它们遵循UML规范,但是这些工具绘制出来的类图存在着细微的差别。本书采用MagicDraw绘制所有类图,下面我们以一个框图编辑器为例介绍该软件的一些约定。

如图1 1所示,类Diagram表示一个框图,类Shape表示抽象意义的图形元素,类Circle和Rectangle表示圆形、矩形的图形元素,它们是Shape的子类。UML使用尾部位三角形的箭头来表示类之间的继承关系。

一个类被表示为一个最多具有3行的矩形框,第1行是类的名字,第2行罗列该类的数据成员,第3行罗列该类的成员函数,第2行、第3行可以被单独或者全部隐藏起来。每个数据成员(或者成员函数)前的"-"表示该成员是该类的私有成员(private),而"+"表示公有成员(public),"#"表示受保护成员(protected)。在数据成员那一行,冒号左边的是数据成员的名字,右边的是数据成员的类型,这部分可被省略。例如,类Diagram含有数据成员elements,表示一个框图含有哪些图形元素。它还含有数据成员fileName,表示以什么文件名保存该框图的信息。以上两个数据成员的类型分别为vector<Shape>以及string。

 
图1 1  使用MagicDraw绘制的类图

如果一个成员函数为纯虚函数,它的名字被显示为斜体,对应的类成为抽象类,类名也被显示为斜体。例如,类Shape表示抽象意义上的几何图形,其成员函数display()无法显示一个抽象的几何图形,因而被定义为一个纯虚函数。在UML类图中,它们的名字都被显示为斜体。

图1-1中,一端为实心菱形的箭头表示类之间的Composition关系。这种关系表示一个类的对象由另外一个类的对象组成。简单地说,就是表示"部分"与"全部"的关系。本例中的这个箭头表示一个框图(类Diagram的对象)"包含"多个几何图形(类Shape的对象,但实际上是Circle或者Rectange的对象,因为Shape是一个抽象类)。箭头正上方的字符串"contains"表示这两个类的关系。箭头左右两侧的数字揭示了相关对象之间的数量对应关系:给定类Diagram的一个对象(表示一个框图),会有类Shape的0到多个对象(实际上仍然是Circle或者Rectangle的对象)被包含在这个框图中;给定Shape的一个对象,只会有一个框图包含这个图形元素。

图1-1中,给定类Diagram的一个对象,通过其数据成员elements可以访问该框图所包含的任意一个图形元素。然而,给定Shape的一个对象,我们却无法简单地依据其数据成员找到它所属的框图对象。UML将这种属性称为可达性(navigability)。单向的可达性用箭头表示,如图1-1所示,而双向的可达性则用不带箭头的实线表示。

类之间有多种关系,上面的Aggregation关系只是其中的一种。在这些关系中,有两种关系和Aggregation关系存在着逻辑上的联系:Association关系以及Composition关系。在绘制类图时,要注意它们之间的联系与区别。

Association,表示两个类之间存在着语义上的关联。两个类是相互独立的,不一定有包含关系。UML用一个实线来表示这种关系,比如图1 2中类Venue和Event之间的关系:当在某个地方举办某个活动的时候,这两个类的对象会有语义上的联系,但是并不存在谁包含谁的关系。

Aggregation,如前文所述,表示"部分"与"全部"的关系,一个类的对象会包含另外一个类的对象,但是,可以有多个包含者包含同一个对象。当包含者被析构时,被包含者不一定被析构。UML用一端为空心菱形的实线来表示这种关系,比如图1 2中类Team和Person之间的关系。一个团队包含多个人,而一个人可以隶属于多个团队。当一个团队被解散时,团队成员依旧存在。

Composition,也表示"部分"与"全部"的关系,但是其中的"部分"只能够隶属于最多一个"全部"。当"全部"被删除时,其中的"部分"也必须被删除。UML用一端为实心菱形的一条实线来表示这种关系,比如前文所述的类Diagram和Shape之间的关系。一个框图可以包含一个或者多个图形元素,但是一个图形元素只能隶属于一个框图。当该框图被保存、关闭后,所有的图形元素将被析构。有的文献也将这种关系称为composition aggregation。

 
图1 2  类之间的几种关联关系

这几种关系之间的逻辑联系是显而易见的:按照association,aggregation,composition的次序,约束条件越来越多,因此,aggregation是association的一种特例,而composition又是aggregation的一种特例。但是这几个概念之间也的确存在着区别。并非所有的association都是aggregation,比如类Venue和Event之间存在着关联关系,但是根本就不存在包含关系。另外,并非所有的aggregation都是composition,比如类Team和Person的关系。

在绘制UML类图的时候,我们应该使用尽量精确的关联关系来标注两个类的关系。也就是说,如果两个类之间存在composition的关系,我们就不要使用aggregation或者association来标注。如果两个类之间存在aggregation的关系,我们就不要使用association来标注。只有这样,所绘制的类图才能够精确地揭示相关对象之间的关联关系。

例如,为了描述一个手机的机械结构,我们可以使用图1 3左侧的类图。一个手机含有多个零件(part),比如LCD显示屏、键盘按钮、电池等。一些零件可以组成一个组件(assembly),比如由电阻、电容、芯片等组成的射频信号发射模块。而较小的组件和一些零件可以组成更大的组件,比如由射频信号发射模块、充电模块、音频处理模块等组成的手机主板。由于零件和组件都是更大组件的一个组成部分,我们用基类component来描述它们的共同属性。类Assembly和Component之间应该是composition的关联关系,这是由于某一个component只可能隶属于一个assembly,对某一个assembly的删除操作必然导致其中所有component的删除。

仅仅使用association关系来描述类Assembly和Component之间的关系是不精确的。   图1 3右侧的类图存在错误情形:

① 设有一个assembly的对象a,它可以包含一个component的对象。由于assembly是component的子类,被包含的对象可以是对象a,此时,就出现了对象a包含其自身的错误情形。

② 设有两个assembly的对象a和b。a可以包含一个component的对象。由于b可以被看做一个component的对象,因而a可以包含b。而同时,b也可以包含一个component的对象,比如a,因而b可以包含a。这样,就出现了a和b相互包含的错误情形。

 
(点击查看大图)图1 3  描述手机机械结构的两个类图

当我们使用图1 3左侧的composition关联关系来描述类Assembly和Component之间的关系时,就不会出现上述两种错误的情形。这是由于composition是aggregation关系的一种,而UML约定aggregation关系必须具备以下两个性质:

(1)反自反(anti-symmetry),即一个对象不能够和自身具有aggregation关系。

(2)传递(transitivity)。如果对象a是b的一个部分,而b是c的一个部分,则a一定是c的一个部分。依据反自反性质,错误情形①可以被排除。在错误情形②中,a包含b,b包含a,依据传递性质,会推导出a包含a自身,这违背了反自反性质,所以错误情形②也可以被排除。可见,使用精确的关联关系可以正确地描述软件系统中各个类之间的关系。

本节只是对UML类图的简要介绍。如果读者需要学习UML,可以参考文献[3]。如果需要了解一个UML术语的严格定义,可以参阅UML官方网站www.uml.org上的语言规范。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇13.7.1 QListWidget(1) 下一篇2.4 主控台的输入与输出

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: