第5章类图和对象图.docx

上传人:b****4 文档编号:3593954 上传时间:2022-11-24 格式:DOCX 页数:27 大小:213.68KB
下载 相关 举报
第5章类图和对象图.docx_第1页
第1页 / 共27页
第5章类图和对象图.docx_第2页
第2页 / 共27页
第5章类图和对象图.docx_第3页
第3页 / 共27页
第5章类图和对象图.docx_第4页
第4页 / 共27页
第5章类图和对象图.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

第5章类图和对象图.docx

《第5章类图和对象图.docx》由会员分享,可在线阅读,更多相关《第5章类图和对象图.docx(27页珍藏版)》请在冰豆网上搜索。

第5章类图和对象图.docx

第5章类图和对象图

第5章类图和对象图

5.1类的定义

在UML中,有两个图非常重要,一个是第3章中介绍的用例图,另一个是本章将要介绍的类图。

Rumbaugh对类的定义是:

类是具有相似结构、行为和关系的一组对象的描述符。

在UML中,类表示划分成3个格子的长方形,如图5.1所示。

图5.1UML中表示类的符号

在图5.1所示的类中,类名是Shape,共有4个属性,分别为origin、size、fillColor和count,其中属性count有一下划线,表示该属性是静态属性。

Shape类有Shape()、move()、resize()和display()方法。

其中方法Shape()的版型为<>,表示该方法是构造方法,而Shape类是一个版型为Graphics的类。

对于版型的定义在5.5节中还会介绍。

在定义类的时候,类的命名应尽量应用领域中的术语,应明确、无歧义,以利于开发人员与用户之间的相互理解和交流。

一般而言,类的名字是名词。

在UML中,类的命名分simplename和pathname两种形式,其中simplename形式的类名就是简单的类的名字。

而pathname形式的类名还包括了包名。

例如,下面是pathname形式的类名:

Banking:

:

CheckingAccount

其中Banking是包名,CheckingAccount是包Banking中的一个类。

5.1.1.类的属性

属性在类图标的属性分隔框中用文字串说明,最新的UML规范说明1.5版本中定义属性的格式为:

[可见性]属性名[:

类型]['['多重性[次序]']'][=初始值][{特性}]

根据详细程度的不同,每条属性可以包括属性的可见性、属性名称、类型、多重性、初始值和特性。

其中特性是用户对该属性性质的一个约束说明。

例如{只读}这样的特性说明该属性的值不能被修改。

上面表示属性的格式中,除了用''括起来的方括号表示的是一个具体的字符外,其他方括号表示该项是可选项。

例5.1属性声明的一些例子。

+size:

Area=(100,100)

#visibility:

Boolean=false

+default-size:

Rectangle

#maximum-size:

Rectangle

-xptr:

XwindowPtr

colors:

Color[3]

points:

Point[2..*ordered]

name:

String[0..1]

需要说明的是,对属性可见性(visibility)的表示,UML和Rose采用不同的符号,UML规范中规定的是用+、#、-等符号,而Rose中采用、、等图形符号表示(参见图5.1)。

对于例5.1中的points属性和name属性,需要注意它们的多重性部分。

多重性声明并不是表示数组的意思。

points的多重性为2..*,表示该属性值有两个或多个,同时这些值之间是有序的(因为有ordered指明)。

而name这个属性的多重性为[0..1],表示name有可能有一个值,也有可能值为null。

特别需要注意的是,name:

String[0..1]并不是表示name是一个String数组。

从理论上讲,一个类可以有无限多个属性,但一般不可能把所有的属性都表示出来,因此在选取类的属性时应只考虑那些系统会用到的特征。

原则上,由类的属性应能区分每个特定的对象。

5.1.2类的操作

操作(operation)用于修改、检索类的属性或执行某些动作,操作通常也称为功能。

但是它们是被约束在类的内部,只能作用到该类的对象上。

操作在类图的操作分隔框中用文字串说明,UML规范说明1.5中规定操作的格式为:

[可见性]操作名[(参数列表)][:

返回类型][{特性}]

其中方括号表示该项是可选项,而{特性}是一个文字串,说明该操作的一些有关信息,例如{query}这样的特性说明表示该操作不会修改系统的状态。

操作名、参数列表和返回类型组成操作接口。

接口与第2章中所介绍的操作的特征标记(signature)这个概念很相似,但也有细微的差别。

操作的特征标记一般只包括操作名和参数列表,而不包括返回类型,但接口是包括返回类型的。

例5.2操作声明的一些例子。

+display():

Location

+hide()

#create()

-attachXWindow(xwin:

XwindowPtr)

需要说明的是,对操作可见性(visibility)的表示,UML和Rose采用不同的符号。

UML规范中规定的是用+、#、-等符号,而Rose中采用、、等图形符号表示(参见图5.1)。

5.2类之间的关系

一般说来,类之间的关系有:

关联、聚集、组合、泛化、依赖等,下面将对这些关系进行详细说明。

5.2.1关联

关联(association)是模型元素间的一种语义联系,它是对具有共同的结构特性、行为特性、关系和语义的链(link)的描述。

在上面的定义中,需要注意链这个概念,链是一个实例,就像对象是类的实例一样,链是关联的实例,关联表示的是类与类之间的关系,而链表示的是对象与对象之间的关系。

在类图中,关联用一条把类连接在一起的实线表示。

如图5.2所示。

图5.2类之间的关联关系图5.3类之间的单向关联关系

一个关联可以有两个或多个关联端(associationend),每个关联端连接到一个类。

关联也可以有方向,可以是单向关联(uni-directionalassociation)或双向关联(bi-directionalassociation)。

图5.2表示的是双向关联,图5.3表示的是从类A到类B的单向关联。

关联是类图中非常重要的一种关系,这里以实现时相应的Java代码来帮助理解关联关系。

可以在Rose中创建如图5.3所示的类图,并用Rose生成Java代码,代码如下所示。

类A的代码:

类B的代码:

从上面的代码中可以看到,在类A中,有一个属性theB,其类型为B,而在类B中,没有相应的类型为A的属性。

如果把这个单向关联改为双向关联,则生成的类B的代码中,会有相应的类型为A的属性。

另外代码中有类似@roseuid3DAFBF0F01FC这样的语句,称作代码标识号。

他的作用是标识代码中的类、操作和其他模型元素。

在双向工程(正向工程和逆向工程)中,可以使代码和模型同步。

1.关联名

可以给关联加上关联名,来描述关联的作用。

如图5.4所示是使用关联名的一个例子,其中Company类和Person类之间的关联如果不使用关联名,则可以有多种解释,如Person类可以表示是公司的客户、雇员或所有者等。

但如果在关联上加上Employs这个关联名,则表示Company类和Person类之间是雇佣(Employs)关系,显然这样语义上更加明确。

一般来说,关联名通常是动词或动词短语。

当然,在一个类图中,并不需要给每个关联都加上关联名,给关联命名的原则应该是该命名有助于理解该模型。

事实上,一个关联如果表示的意思已经很明确了,再给它加上关联名,反而会使类图变乱,只会起到画蛇添足的作用。

图5.4使用关联名的关联

2.关联的角色

关联的两端可以某种角色参与关联。

例如在图5.5中,Company类以employer的角色名、Person类以employee的角色名参与关联,employer和employee称为角色名。

如果在关联上没有标出角色名,则隐含地用类的名称作为角色名。

角色还具有多重性(multiplicity),表示可以有多少个对象参与该关联。

在图5.5中,雇主(公司)可以雇佣多个雇员,表示为0..n;雇员只能被一家雇主雇佣,表示为1。

图5.5关联的角色

在UML中,多重性可以用下面的格式表示:

0..1

0..*(也可以表示为0..n)

1(1..1的简写)

1..*(也可以表示为1..n)

*(即0..n)

7

3,6..9

0(0..0的简写)(表示没有实例参与关联,一般不用)

可以看到,多重性是用非负整数的一个子集来表示的。

3.关联类

关联本身可以有特性,通过关联类()可以进一步描述关联的属性、操作以及其他信息。

关联类通过一条虚线与关联连接。

图5.6中的Contract类是一个关联类,Contract类中有属性salary,这个属性描述的是Company类和Person类之间的关联的属性,而不是描述Company类或Person类的属性。

图5.6使用关联类的关联

为了有助于理解关联类,这里也用Rose生成相应的Java代码,共3个类,如下所示。

类Company的代码:

publicclassCompany{

privateStringcompanyName;

publicPersonemployee[];

}

类Person的代码:

publicclassPerson{

privateStringpersonName;

protectedCompanyemployer;

}

类Contract的代码:

publicclassContract{

privateDoublesalary;

}

由于指定了关联角色的名字,所以生成的代码中就直接使用关联角色名作为所声明的变量的名字,如employee、employer等。

另外,employer的可见性是protected,也在生成的代码中体现出来。

因为指定关联的employee端的多重性为n,所以在生成的代码中,employee是类型为Person的数组。

另外可以发现所生成的Java代码都没有构造方法。

这是因为在生成代码前,已经把Rose的Tools→Options→Java的Class选项的GenerateDefaultConstructor属性设置为False,即要求生成代码时不生成类的默认构造方法。

4.关联的约束

对于关联可以加上一些约束,以加强关联的含义。

如图5.7所示是两个关联之间存在异或约束的例子,即Account类或者与Person类有关联,或者与Corporation类有关联,但不能同时与Person类和Corporation类都有关联。

约束是UML中的3种扩展机制之一,另外两种扩展机制是版型(stereotype)和标记值(taggedvalue)。

当然,约束不仅可以作用在关联这个建模元素上,也可以作用在其他建模元素上。

图5.7带约束的关联

5.限定关联

在关联端紧靠类图标处可以有限定符(qualifier),带有限定符的关联称为限定关联(qualifiedassociation)。

限定符的作用就是在给定关联一端的一个对象和限定符值以后,可确定另一端的一个对象或对象集。

使用限定符的例子如图5.8所示。

图5.8限定符和限定关联

图5.9限定关联和一般关联

图5.8表示的意思是,一个Person可以在bank中有多个account。

但给定了一个account值后,就可以对应一个Person值,或者对应的person值为null,因为Person端的多重性为0..1。

这里的多重性表示的是person和(bank,account)之间的关系,而不是person和bank之间的关系。

即:

(bank,account)→0个或1个person

Person→多个(bank,account)

但图5.8种并没有说明Person类和Bank类之间是1对多的关系还是1对1的关系,极可能一个person只对应一个bank,也可能一个person对应多个bank。

如果一定要明确一个person对应的是一个bank还是多个bank,则需要在Person类和Bank类之间另外增加关联来描述。

如图5.9表示一个person可以对应一个或多个bank。

需要注意的是,限定符是关联的属性,而不是类的属性。

也就是说,在具体实现图5.8中的结构时,account这个属性有可能是Person类中的一个属性,也可能是Bank类中的一个属性(当然,这里在Bank类中包含account属性并不好),也可能是在其他类中有一个account属性。

限定符这个概念在设计软件时非常有用,如果一个应用系统需要根据关键字对一个数据集做查询操作,则经常会用到限定关联。

引入限定符的一个目的就是把多重性从n将为1或0..1,这样如果做查询操作,则这个查询操作的效率会很高。

所以在使用限定符时,如果限定符另一端的多重性仍为n,则引入这个限定符的作用就不是很大。

因为查询结果仍然还是一个结果集,所以也可以根据多重性来判断一个限定符的设计是否合理。

6.关联的种类

按照关联所连接的类的数量,类之间的关联可分为自返关联、二元关联和N元关联共3种关联。

自返关联(reflexiveassociation)又称递归关联(recursiveassociation),是一个类与自身的关联,即同一个类的两个对象间的关系。

自返关联虽然只有一个被关联的类,但有两个关联端,每个关联端的角色不同。

自返关联的例子如图5.10所示。

图5.10自返关联

对于图5.10中的类,在Rose中所生成的Java代码如下所示:

类EnginePart的代码:

publicclassEnginePart{

publicEngineParttheEnginePart[];

/**

*@roseuid3E9290390281

*/

publicEnginePart(){}

}

二元关联(binaryassociation)是在两个类之间的关联,对于二元关联,前面已经举了很多例子,这里就不再举例说明了。

N元关联(n-aryassociation)是在3个或3个以上类之间的关联。

N元关联的例子如图5.11所示,Player、Team和Year这3个类之间存在三元关联,而Record类是关联类。

N元关联中多重性的意义是,在其他N-1个实例值确定的情况下,关联实例元组的个数。

如在图5.11中,多重性表示的意思是在某个具体年份(year)和运动队(team)中,可以有多个运动员(player);一个运动员在某一个年份中,可以在多个运动队中服役;同一个运动员在同一个运动队中可以服役多年。

N元关联没有限定符的概念,也没有聚集、组合等概念。

(在5.2.2节将介绍聚集、组合概念)。

需要说明的是,在UML的规范说明中,有N元关联这个建模元素,用菱形表示。

在Rose2003中,并不能直接表示N元关联,但可以在类图中创建一个类的版型来模拟画出N元关联(图5.11即是在Rose2003中增加了一个表示N元关联的版型后画出的)。

至于如何在Rose2003中加入用户自己要用的版型,这涉及到Rose的扩展机制,在第17章介绍Rose2003开发工具时再详细讨论。

5.2.2聚集和组合

聚集(aggregation)是一种特殊形式的关联。

聚集表示类之间整体与部分的关系。

在对系统进行分析和设计时,需要描述中的“包含”,“组成”、“分为…部分”等词常常意味着存在聚集关系。

组合(composition)表示的也是类之间整体与部分的关系,但组合关系中的整体与部分具有同样的生存期。

也就是说,组合是一种特殊形式的聚集。

如图5.12和如图5.13所示分别是聚集关系和组合关系的例子。

图5.12聚集关系图5.13组合关系

图5.12中的Circle类和Style类之间是聚集关系。

一个圆可以有颜色、是否填充这些样式(style)方面的属性,可以用一个style对象表示这些属性,但同一个style对象也可以表示别的对象如三角形(triangle)的一些样式方面的属性,也就是说,style对象可以用于不同的地方。

如果circle这个对象不存在了,不一定意味着style这个对象也不存在了。

图5.13中的Circle类和Point类之间是组合关系。

一个圆可以由半径和圆心确定,如果圆不存在了,那么表示这个圆的圆心也就不存在了,所以Circle类和Point类是组合关系。

聚集关系的实例是传递的,反对称的,也就是说,聚集关系的实例之间存在偏序关系,即聚集关系的实例之间不能形成环。

需要注意的是,这里说的是聚集关系的实例(即链)不能形成环,而不是说聚集关系不能形成环。

事实上,聚集关系可以形成环。

在类图中使用聚集关系和组合关系的好处是简化了对象的定义,同时支持分析和设计时类的重用。

聚集和组合是类图中很重要的两个概念,但也是比较容易混淆的概念,在实际运用时往往很难确定使用聚集关系还是用组合关系。

事实上,在设计类图时,设计人员是根据需求分析描述的上下文来确定是使用聚集关系还是组合关系。

对于同一个设计,可能采用聚集关系和采用组合关系都是可以的,不同的只是采用哪种关系更贴切些。

下面列出聚集和组合之间的一些区别:

聚集关系也称为“has-a”关系,组合关系也称为“contains-a”关系。

聚集关系表示事物的整体/部分关系的较弱的情况,组合关系表示事物的整体/部分关系的较强的情况。

在聚集关系中,代表部分事物的对象可以属于多个聚集对象,可以为多个聚集对象所共享,而且可以随时改变它所从属的聚集对象。

代表部分事物的对象与代表聚集事物对象的生存期无关,一旦删除了它的一个聚集对象,不一定也就随即删除代表部分事物的对象。

在组合关系中,代表整体事物的对象负责创建和删除代表部分事物的对象,代表部分事物的对象只属于一个组合对象。

一旦删除了组合对象,也就随即删除了相应的代表部分事物的对象。

5.2.3泛化关系

泛化(generalization)定义了一般元素和特殊元素之间的分类关系,如果从面向对象程序设计语言的角度来说,类与类之间的泛化关系就是平常所说的类之间的继承关系。

泛化关系也称为“a-kind-of”关系。

在UML中,泛化关系不仅仅是类与类之间才有,像用例、参与者、关联、包、构件(component)、数据类型(datatype)、接口(interface)、节点(node)、信号(signal)、子系统(subsystem)、状态(state)、事件(event)、协作(collaboration)等这些建模元素之间也可以有泛化关系。

UML中用一头为空心三角形的连线表示泛化关系。

如图5.14所示是类之间泛化关系的例子。

图5.14泛化关系

在图5.14中,Swimmer类和Golfer类是对Athlete类的泛化,其中Athlete类的名字用斜体表示,表示该类是一个抽象类,而Swimmer类和Golfer类的名字没有用斜体,表示这两个类是具体类。

5.2.4依赖关系

假设有两个元素X、Y,如果修改元素X的定义可能会导致对另一个元素Y的定义修改,则称元素Y依赖于元素X。

图5.15依赖关系

对于类而言,依赖(dependency)关系可能有各种原因引起,如一个类向另一个类发送消息,或者一个类是另一个类的数据成员类型,或者一个类是另一个类的操作的参数类型等。

如图5.15所示是类之间依赖关系的例子,其中Schedule类中的add操作和remove操作都有类型为Course的参数,因此Schedule类依赖于Course类。

有时依赖关系和关联关系比较难区分。

事实上,如果类A和类B之间有关联关系,那么类A和类B之间也就有依赖关系了。

但如果两个类之间有关联关系,那么一般只要表示出关联关系即可,不用再表示这两个类之间还有依赖关系。

而且,如果一个类图中有过多的依赖关系,反而会使类图难以理解。

与关联关系不一样的是,依赖关系本身不生成专门的实现代码。

另外,与泛化关系类似,依赖关系也不仅仅只是限于类之间,其他建模元素,如用例和用例之间,包与包之间也可以有依赖关系。

5.3派生属性和派生关联

派生属性(derivedattribute)和派生关联(derivedassociation)是指可以从其他属性和关联计算推演得到的属性和关联。

例如,如图5.16所示的Person类的age属性即为派生属性,因为一个人的年龄可以从当前日期和出生日期推算出来。

在类图中,派生属性和派生关联的名字前需加一个斜杠“/”。

如图5.17所示是派生关联的例子,WorkForCompany为派生关联。

一个公司由多个部门组成,一个人为某一个部门工作,那么可推演出这个人为这个公司工作。

图5.16派生属性

图5.17派生关联

在生成代码时,派生属性和派生关联不产生相应的代码。

指明某些属性和关联是派生属性和派生关联有助于保持数据的一致性。

5.4抽象类和接口

抽象类(abstractclass)是不能直接产生实例的类,因为抽象类中的方法往往只是一些声明,而没有具体的实现,因此不能对抽象类实例化。

UML中通过把类名写成斜体字来表示抽象类,图5.14中的Athlete类即为抽象类。

接口是类的<>版型,对于版型这个概念在5.5节中还会介绍。

如图5.18所示是接口的3种表示方式。

图5.18接口的3种表示方式

在Rose中,一些常用的版型一般有Icon、Label和Decoration这3种表示形式。

但如果版型使用户自己增加的,一般没有Icon和Decoration这两种表示形式,除非用户自己提供相应的图符文件,这涉及要修改Rose的配置文件。

在第17章介绍如何使用Rose开发工具时,再介绍如何修改Rose的配置文件。

需要注意的是,UML中接口的概念和一般的程序设计语言(如Java)中接口的概念稍有不同。

例如,Java中的接口可以包含属性,但UML中的接口不包括属性,只包含方法的声明。

接口与抽象类很相似,但两者之间存在不同的地方:

接口不能含有属性,而抽象类可以含有属性;接口中声明的所有方法都没有实现部分,而抽象类中某些方法可以有具体的实现。

5.5版型

版型是UML的3种扩展机制之一,UML中的另外两种扩展机制是标记值和约束。

Stereotype这个词来源于印刷业中的术语,一般在进行正式印刷前,需要进行制版,然后根据做好的版型进行批量印刷。

在2.4节介绍UML的构成时,已提到UML中的基本构造块包括事物(thing)、关系(relationship)、图(diagram)这3种类型。

版型是建模人员在已有的构造块上派生出的新构造块,这些新构造块是和特定问题相关的。

需要注意的是,版型必须定义在UML中已经有定义的基本构造块之上,是在已有元素上增加新的语义,而不是增加新的文法结构。

如果把基本构造块比作一门语言的词汇的话,那么版型就是扩展了整个词汇表。

版型是UML中非常重要的一个概念,UML之所以有强大而灵活的表示能力,与版型这个扩展机制有很大的关系。

版型可以应用于所有类型的模型元素,包括类、结点、构件、注解、关系、包、操作等。

当然,在某些建模元素上定义的版型比较多,在另一些建模元素上可能就很少定义版型,如一般很少在注解上定义版型,尽管可以这样做。

UML中预定义了一些版型,如接口是类的版型,子系统是包的版型等。

当然用户也可以自己定义版型。

下面给出一些版型的例子,以加深对版型的理解。

如图5.19所示是参与者(actor)的3种表示方式。

在第3章介绍用例的时候已提到参与者事实上是一个版型化的类,其版型为<>。

图5.19Actor的3种表示方式

由于Actor事实上就是一个类,所以也可以给Actor添加属性和操作,就像给类添加属性和操作一样。

如图5.20所示是带有操作的Actor的例子。

除了预定义的版型外,用户也可以自定义版型,如图5.21所示是自定义版型的例子。

图5.20Actor及其操作图5.21自定义版型

图5.21中用<

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1