UML–类详解

http://www.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/

基础

如先前所关联的,类图的目标是显示建模系统的品种。在大多数的 UML
模型中那几个项目包蕴:

  • 接口

  • 数据类型

  • 组件

UML
为那个项目起了一个专程的名字:“分类器”。平常地,你可以把分类器当做类,但在技术上,分类器是更进一步宽泛的术语,它依然引用上边的其它两种档次为好。

类名

类的 UML 表示是一个长方形,垂直地分成四个区,如图 1
所示。顶部区域显示类的名字。中间的区域列出类的属性。底部的区域列出类的操作。当在一个类图上画一个类元素时,你不可以不要有上边的区域,上边的二个区域是可挑选的(当图描述仅仅用于体现分类器间关系的高层细节时,上面的三个区域是不需要的)。图
1 出示一个航程班机怎么着作为 UML
类建模。正如我们所能见到的,名字是 Flight,咱们得以在中游区域看到Flight类的3个特性:flightNumber,departure提姆e

flightDuration。在底层区域中大家得以看出Flight类有四个操作:delayFlight
和 getArrivalTime。

C++ 1

图 1: Flight类的类图

类属性列表

类的属性节(中部区域)在分隔线上列出每一个类的习性。属性节是可挑选的,假诺一用它,就含有类的列表突显的各种属性。该线用如下格式:

name : attribute type
flightNumber : Integer

持续大家的Flight类的例子,大家可以动用性质类型音讯来叙述类的属性,如表 1
所示。

表 1:具有关联类型的Flight类的习性名字

属性名称 属性类型
flightNumber Integer
departureTime Date
flightDuration Minutes

在业务类图中,属性类型一般与单位符合,那对于图的也许读者是有意义的(例如,秒钟,加元,等等)。可是,用于转移代码的类图,必要类的品质类型必须界定在由程序语言提供的品种之中,或带有于在系统中贯彻的、模型的档次之中。

在类图上显得所有默许值的特定属性,有时是有效的(例如,在银行账户应用程序中,一个新的银行账户会以零为开始值)。UML
规范允许在属性列表节中,通过行使如下的符号作为默认值的标识:

name : attribute type = default value

比方来说:

balance : Dollars = 0

显示属性默许值是可挑选的;图 2
显示一个银行账户类具有一个名为 balance的品种,它的默许值为0。

C++ 2

图 2:突显默许为0美金的balance属性值的银行账户类图。

类操作列表

类操作记录在类图长方形的第七个(最低的)区域中,它也是可接纳的。和品质一样,类的操作以列表格式突显,每个操作在它自己线上。操作使用下列记号表现:

    name(parameter list) : type of value returned

上边的表 2 中Flight类操作的照射。

表 2:从图 2 映射的Flight类的操作

操作名称 返回参数 值类型
delayFlight
Name Type
numberOfMinutes Minutes
N/A
getArrivalTime N/A Date

图3显示,delayFlight 操作有一个Minutes类型的输入参数 —
numberOfMinutes。但是,delayFlight
操作没有重临值。 1 当一个操作有参数时,参数被放在操作的括号内;每个参数都拔取那样的格式:“参数名:参数类型”。

C++ 3

图 3:Flight类操作参数,包含可挑选的“in”标识。

当文档化操作参数时,你也许使用一个可挑选的提示器,以体现参数到操作的输入参数、或输出参数。那几个可挑选的提醒器以“in”或“out”出现,如图3中的操作区域所示。一般的话,除非将应用一种早期的主次编程语言,如Fortran
,那几个提示器可能会具有帮忙,否则它们是不须要的。不过,在
C++和Java中,所有的参数是“in”参数,而且根据UML规范,既然“in”是参数的默许类型,一大半人将会遗漏输入/输出提示器。

继承

在面向对象的统筹中一个要命关键的概念,继承,指的是一个类(子类)继承除此以外的一个类(超类)的均等功效,并增添它和谐的新职能(一个非技术性的比喻,想象我一连了自家二姨的貌似的音乐力量,不过在自我的家里,我是绝无仅有一个玩电吉他的人)的能力。为了在一个类图上建模继承,从子类(要连续行为的类)拉出一条闭合的,单键头(或三角形)的实线指向超类。考虑银行账户的门类:图
4 呈现 CheckingAccount 和 SavingsAccount 类怎样从 BankAccount
类继承而来。

C++ 4

图 4: 继承通过指向超类的一条闭合的,单箭头的实线表示。

在图 4 中,继承关系由种种超类的独立的线画出,那是在IBM Rational
罗丝和IBM Rational
XDE中行使的办法。可是,有一种叫做 树标记的预备格局可以画出继承关系。当存在八个或更加多子类时,如图
4 中所示,除了继续线象树枝一样混在协同外,你可以动用树形记号。图 5
是重绘的与图 4 一样的后续,不过这一次运用了树形记号。

C++ 5

图 5: 一个应用树形记号的延续实例

抽象类及操作 
密切的读者会注意到,在图 4 和 图5
中的图中,类名BankAccount和withdrawal操作使用斜体。这代表,BankAccount
类是一个抽象类,而withdrawal方法是空洞的操作。换句话说,BankAccount
类使用withdrawal规定抽象操作,并且CheckingAccount 和 SavingsAccount
四个子类都各自地实践它们分别版本的操作。

但是,超类(父类)不必然如若抽象类。标准类作为超类是正常的。

关联 
当你系统建模时,特定的靶子间将会相互关系,而且这几个涉及本身须要被明晰地建模。有多种关系。在这一局地中,我将会谈谈它们中的四个– 双向的涉嫌和单向的涉嫌,而且自己将会在Beyond the
basics
一部分探究剩下的三种关系类型。请留意,关于哪天该应用每序列型涉及的详实座谈,不属于本文的限定。相反的,我将会把紧要集中在每种关系的用途,并表明怎样在类图上画出涉及。

双向(标准)的关联 
波及是四个类间的连结。关联总是被假定是双向的;那象征,八个类相互领悟它们间的维系,除非你限定一些任何项目的涉嫌。回看一下Flight
的事例,图 6 突显了在Flight类和Plane类之间的一个正规项目标关联。

C++ 6

图 6:在一个Flight类和Plane类之间的双向关联的实例

一个双向关联用三个类间的实线表示。在线的任一端,你放置一个角色名和多重值。图
6
展现Flight与一个一定的Plane相关联,而且Flight类知道这些涉及。因为角色名以Plane类表示,所以Plane承担关联中的“assignedPlane”角色。紧接于Plane类后边的多重值描述0…1代表,当一个Flight实体存在时,可以有一个或从不Plane与之提到(也就是,Plane可能还尚未被分配)。图
6
也显得Plane知道它与Flight类的关联。在这么些涉及中,Flight承担“assignedFlights”角色;图
6
的图告诉大家,Plane实体可以不与flight关联(例如,它是一架全新的飞行器)或与从不上限的flight(例如,一架已经当兵5年的飞机)关联。

是因为对这么些在关乎尾部可能出现的多重值描述感到迷惑不解,上边的表3列出了一些多重值及它们含义的例子。

表 3: 多重值和它们的表示

唯恐的多重值描述

表示

含义

0..1

0个或1个

1

只能1个

0..*

C++,0个或多个

*

0个或八个

1..*

1个或我个

3

只能3个

0..5

0到5个

5..15

5到15个

单向关系 
在一个单向关系中,七个类是城门失火的,可是唯有一个类知道这种关联的存在。图 7
显示单向关系的透支财务报告的一个实例。

C++ 7

图 7: 单向关系一个实例:OverdrawnAccountsReport 类 BankAccount 类,而
BankAccount 类则对关联一窍不通。

一个单方面的关联,表示为一条带有指向已知类的怒放箭头(不关门的箭头或三角形,用于标志继承)的实线。似乎标准提到,单向关系包罗一个角色名和一个多重值描述,可是与正式的双向关联区其他时,单向关系只包括已知类的角色名和多重值描述。在图
7 中的例子中,OverdrawnAccountsReport 知道 BankAccount 类,而且知道
BankAccount
类扮演“overdrawnAccounts”的角色。但是,和标准提到不一致,BankAccount
类并不知道它与 OverdrawnAccountsReport
相关联。 2

软件包 
不可幸免,即便您正在为一个大的系统或大的事体领域建模,在您的模子少校会有很多分化的分类器。管理所有的类将是一件令人生畏的天职;所以,UML
提供一个名为 软件包的团协会元素。软件包使建模者能够协会模型分类器到名字空间中,那有些象文件系统中的文件夹。把一个系列分为多个软件包使系统成为不难明白,尤其是在各类软件包都表现系统的一个一定部分时。 3

在图中设有两种格局表示软件包。并没有规则必要利用哪类标志,除了用你个人的判定:哪个种类更有利于阅读你画的类图。三种情势都是由一个较小的长方形(用于固定)嵌套在一个大的长方形中初阶的,如图
8 所示。不过建模者必须决定包的成员怎么样表示,如下:

  • 借使建模者决定在大长方形中浮现软件包的积极分子,则怀有的这一个成员 4 需要被停放在长方形里面。其它,所有软件包的名字须求放在软件包的较小长方形之内(如图
    8 的显得)。

  • 如若建模者决定在大的长方形之外突显软件包成员,则兼具将会在图上突显的积极分子都需求被安放长方形之外。为了突显属于软件包的分类器属于,从每个分类器画一条线到里头有加号的圆圆,那一个圆周粘附在软件包之上(图9)。

C++ 8

图 8:在软件包的长方形内突显软件包成员的软件包元素例子

C++ 9

图 9:一个透过连接线表现软件包成员的软件包例子

刺探基础紧要性

在 UML 2
中,驾驭类图的根基更为首要。那是因为类图为拥有的其它协会图提供基本的营造块。如组件或对象图(仅仅是举了些例子)。


回页首

当先基础

到此停止,我一度介绍了类图的功底,可是请继续往下读!在底下的有些中,我将会率领你到你会采取的类图的更主要的方面。那一个包涵UML
2 正规中的接口,别的的三种关系类型,可知性和任何补偿。

接口 
在本文的先头,我指出您以类来设想分类器。事实上,分类器是一个进一步相似的定义,它概括数据类型和接口。

有关哪天、以及哪些高效地在系统结构图中运用数据类型和接口的全部商讨,不在本文的议论范围以内。既然那样,我干吗要在此地提及数据类型和接口呢?你也许想在结构图上效仿那一个分类器类型,在那些时候,使用正确的记号来表示,或者至少知道这几个分类器类型是最紧要的。不得法地绘制这个分类器,很有可能将使您的构造图读者觉得混乱,将来的系统将无法适应需要。

一个类和一个接口分裂:一个类可以有它造型的忠实实例,然则一个接口必须至少有一个类来落到实处它。在
UML 2
中,一个接口被认为是类建模元素的特殊化。因而,接口就象类那样绘制,不过长方形的顶部区域也有文件“interface”,如图
10
所示。 5

C++ 10

图 10:Professor类和Student类完成Person接口的类图实例

在图 10
中彰显的图中,Professor和Student类都落实了Person的接口,但并不从它继续。我们了然这或多或少是出于上面五个原因:1)
Person对象作为接口被定义 —
它在目标的名字区域中有“interface”文本,而且大家看来由于Professor和Student对象按照画类对象的条条框框(在它们的名字区域中没有额外的分类器文本)标示,所以它们是 目的。
2) 大家知道继承在那里没有被出示,因为与带箭头的线是点线而不是实线。如图
10
所示,一条带有闭合的单向箭头的 线意味着完毕(或执行);正如大家在图
4 中所见到的,一条带有闭合单向箭头的线意味着继续。

更加多的涉嫌 
在上头,我谈谈了双向关联和单向关系。现在,我将会介绍剩下的三连串型的涉及。

关联类 
在提到建模中,存在部分动静下,你须求包蕴别的类,因为它富含了有关关联的有价值的信息。对于那种境况,你会选拔 关联类 来绑定你的中坚关系。关联类和一般类一样表示。分化的是,主类和关联类之间用一条相交的点线连接。图
11 突显一个航空工业实例的关联类。

C++ 11

图 11:增加关联类 MileageCredit

在图 11 中显得的类图中,在Flight类和 FrequentFlyer
类之间的涉及,暴发了名为
MileageCredit的涉及类。那意味着当Flight类的一个实例关联到 FrequentFlyer
类的一个实例时,将会发生 MileageCredit 类的一个实例。

聚合 
聚拢是一种更加类型的涉嫌,用于描述“总体到一些”的涉及。在主导的集结关系中, 部分类 的生命周期独立于 整体类 的生命周期。

举例来说,大家可以设想, 是一个完好无缺实体,而 车轮 轮胎是整辆车的一局地。轮胎可以在安排到车时的前多少个礼拜被打造,并放置于仓库中。在那个实例中,Wheel类实例清楚地单独地Car类实例而留存。然则,有些景况下, 部分 类的生命周期并  独立于 整体 类的生命周期

那称为合成聚合。举例来说,考虑集团与单位的涉嫌。 商店和机关 都建模成类,在店铺存在从前,部门不能够存在。那里Department类的实例器重于Company类的实例而存在。

让大家更进一步追究基本聚合和重组聚合。

主导聚合 
有成团关系的关联提出,某个类是此外某个类的一片段。在一个会聚关系中,子类实例可以比父类存在更长的时日。为了突显一个集结关系,你画一条从父类到有的类的实线,并在父类的关系末端画一个未填充棱形。图
12 显示车和轮胎间的集结关系的事例。

C++ 12

图 12: 一个相会关联的事例

组成聚合 
重组聚合关系是聚众关系的另一种样式,不过子类实例的生命周期看重于父类实例的生命周期。在图13中,展现了Company类和Department类之间的整合关系,注意组合关系如聚合关系一致绘制,然而这次菱形是被填充的。

C++ 13

图 13: 一个结合关系的例证

在图 13
中的关系建模中,一个Company类实例至少总有一个Department类实例。因为涉嫌是整合关系,当Company实例被移除/销毁时,Department实例也将自行地被移除/销毁。组合聚合的另一个生死攸关成效是有的类只能够与父类的实例相关(举例来说,大家例子中的Company类)。

反射关联 
当今大家已经切磋了富有的涉及类型。似乎您或许注意到的,大家的所有例子已经显示了三个分裂类之间的涉嫌。不过,类也得以运用反射关联与它自身相关联。先河,那说不定没有意思,不过切记,类是抽象的。图
14 彰显一个Employee类怎么样通过manager /
manages角色与它自身有关。当一个类关联到它本身时,那并不表示类的实例与它自己有关,而是类的一个实例与类的另一个实例相关。

C++ 14

图 14:一个反光关联关系的实例

图 14
描绘的关系说贝因美(Friso)个Employee实例可能是此外一个Employee实例的高管。但是,因为“manages”的关系角色有
0..*的多重性描述;一个雇员可能不受任何别的雇员管理。

可见性 
在面向对象的安顿性中,存在属性及操作可知性的记号。UML
识别四体系型的可知性:public,protected,private及package。

UML
规范并不必要质量及操作可知性必须出示在类图上,然而它需求为各样属性及操作定义可知性。为了在类图上的体现可见性,放置可知性标志于属性或操作的名字从前。纵然UML 指定三种可知性类型,然则实际上的编程语言可能增添额外的可知性,或不辅助UML 定义的可见性。表4展现了 UML 支持的可知性类型的两样标志。

表 4:UML 扶助的可知性类型的申明

标志 可见性类型
+ Public
# Protected
Private
~ Package

近期,让大家看一个类,以证实属性及操作的可知性类型。在图 15
中,所有的性质及操作都是public,除了 updateBalance 操作。updateBalance
操作是protected。

C++ 15

图 15:一个 BankAccount 类表达它的品质及操作的可知性


回页首

UML
2 补充

既是我们曾经覆盖了基础和高档大旨,我们将覆盖一些由UML 1.
x增加的类图的新标志。

实例 
当一个系统结营造模时,显示例子类实例有时候是卓有成效的。为了这种布局建模,UML
2
提供 实例规范 元素,它显示在系统中应用例子(或具体)实例的值得注意的新闻。

实例的号子和类一样,然而代表顶端区域中仅局地类名,它的名字是透过拼接的:

Instance Name : Class Name

比方来说:

Donald : Person

因为呈现实例的目标是呈现值得注意的或有关的音信,没要求在您的模型中富含全体实体性质及操作。相反地,仅仅显示感兴趣的质量及其值是一心适用的。如图16所描述。

C++ 16

图 16:Plane类的一个实例例子(只浮现感兴趣的属性值)

但是,仅仅显示一些实例而从不它们的涉及不太实用;因而,UML 2
也同意在实体层的关联/关联建模。绘制关联与一般的类关系的平整平等,除了在建模关联时有一个外加的要求。附加的限制是,关联关系必须与类图的关联相平等,而且涉嫌的角色名字也非得与类图相平等。它的一个例证呈现于图
17 中。在那些事例中,实例是图 6 中类图的例子实例。

C++ 17

图 17:图 6 中用实例代替类的例证

图 17
有Flight类的二个实例,因为类图提出了在Plane类和Flight类之间的关联是 0或多。由此,大家的事例给出了多少个与NX0337
Plane实例相关的Flight实例。

角色 
建模类的实例有时比期望的越来越详细。有时,你或许一味想要在一个较多的貌似层次做类关系的模型。在那种景色下,你应当拔取 角色 记号。角色记号类似于实例记号。为了创制类的角色模型,你画一个方格,并在中间放置类的角色名及类名,作为实体记号,然而在本场馆你无法加下划线。图
18 突显一个由图 14 中图描述的雇员类扮演的角色实例。在图 18
中,大家得以认为,尽管雇员类与它本身有关,关系着实是有关雇员之间扮演COO及团队成员的角色。

C++ 18

图 18:一个类图彰显图14中扮演不相同角色的类

瞩目,你不可能在纯粹类图中做类角色的建模,即使图
18显得你可以这么做。为了选用角色记号,你将会必要选择下边琢磨的内部结构记号。

其中的布局 
UML 2
结构图的更管用的功能之一是新的内部结构记号。它同意你来得一个类或别的的一个分类器怎么样在其中整合。这在
UML 1. x
中是不可以的,因为记号限制你只好显示一个类所拥有的聚众关系。现在,在 UML
2 中,内部的组织记号让你更清楚地出示类的逐条部分如何有限支撑关系。

让咱们看一个实例。在图 18
中大家有一个类图以展现一个Plane类怎么样由八个引擎和多少个控制软件对象组成。从那么些图中省略的东西是突显关于飞机部件怎么着被装配的有的音信。从图
18
的图,你不能表达,是每个控制软件对象说了算三个引擎,仍然一个控制软件对象说了算多个引擎,而另一个操纵一个发动机。

C++ 19

图 19: 只突显对象时期涉及的类图

绘制类的内在结构将会改革那种景色。初步时,你通过用二个区域画一个方格。最上端的区域包罗类名字,而较低的区域包罗类的内部结构,展现在它们父类中肩负不一致角色的片段类,角色中的每个部分类也提到到其余类。图
19 显示了Plane类的内部结构;注意内部结构怎么样澄清混乱性。

C++ 20

图 20:Plane类的内部结构例子。

在图 20 中Plane有两个ControlSoftware 对象,而且每个控制二个引擎。在图左边上的
ControlSoftware(control1)控制引擎 1 和 2 。在图左侧的
ControlSoftware(control2)控制引擎 3 和 4 。