附录1
Software Engineering:A Practitioner’s Approach (Seventh Edition)
UML 简介
关键概念
活动图
类图
通信图
依赖
部署图
泛化
交互框架
多重性
对 象 约 束 语 言
OCL
顺序图
状态图
构造型
泳道
用例图
统一建模语言(Unified Modeling Language,UML)是“绘制软件蓝图的
标准化语言。UML用来可视化、描述、构造和文档化软件密集系统的人工制品”
[Boo05]。换句话说,就像建筑设计师需要为建筑公司设计蓝图一样,软件设计
师也需要创建UML图帮助软件开发者开发软件。如果了解UML的词汇(图示元
素和它们的含义),就可以很轻松地理解和描述一个系统,并向他人解释该系统
的设计。
Grady Booch、Jim Rumbaugh和Ivar Jackson在20世纪90年代中期开发出了
UML语言,引起了广大软件开发人员的强烈反响。UML融合了大量当时软件产
业所使用的具有竞争力的建模表示方法。1997年,UML 1.0被提交给对象管理
组织(Object Management Group,OMG)—一个致力于维护计算机产业使用
规范的非盈利性组织。同年,UML1.0修订成UML1.1后不久就被对象管理组织
采用了。目前的标准是UML2.0 ,也是ISO标准。因为这个标准很新,很多旧
的资料,如[Gam95],没有使用UML符号。
UML2.0提供了13种不同的图供软件建模使用。在本附录中,将仅讨论类图、
部署图、用例图、顺序图、通信图、活动图和状态图。本书使用了这些图。
应该注意,UML图有很多可选功能。UML语言提供了这些选项(有时候是隐藏的),使得
软件工程师能表达系统的所有重要方面。同时,还可以灵活地隐藏图中那些与建模无关的部分,
避免无关的细节将图弄得杂乱。因此,一种特殊功能的省略并不意味着该功能的缺失,它可能
意味着该功能被隐藏了。在本附录中,没有介绍UML图的所有功能,而是重点介绍标准选项,
尤其是本书用到的那些选项。
类图
为了对类建模(包括类的属性、操作和关系以及和其他类的联系 ),UML提供了类图,
类图提供了系统的静态或结构视图。它并不显示图中类的对象之间通信的动态特性。
类图的主要元素是方框,方框是一些用来描述类和接口的图符。每个方框都被水平地划分
为多个部分。顶层部分包含类的名字,中间部分列出了类的属性。属性是指类的对象所知道并
能一直提供的内容。属性通常被实现为类的域,但并不需要如此。属性可以是一些数值,这些
数值是由类从它的实例变量中计算出来的,或是从组成它的其他对象中得到的。比如,对象可
以时刻知道当前时间并在你查询时反馈给你。因此,它适合列出当前时间作为该类对象的属性。
然而,对象不可能将该时间存储在它的实例变量中。如果这样的话,它需要一直不断地更新该
字段。作为替代,对象更可能在你请求时间时计算出当前时间(例如,通过查询其他类的对象)。
本附录由Dale Skrien提供并改编自他的著作《An Introduction to Object-Oriented Design and Design Patterns
in Java》(McGraw-Hill,2008)。所用内容已经授权。
OMG已经于2009年2月发布了UML2.2。可在http://www.omg.org/找到。—译者注
如果你不熟悉面向对象的概念,可参考附录2中给出的简要介绍。
608 附录1 UML简介
类图的第三部分包含类的操作或行为。操作是指类的对象所能做的事情,通常实现为类的方法。
图A1-1介绍了一个简单例子,用Thoroughbred类对优良种马建模。它有3个属性—
mother、father和birthyear,还有3个操作:getCurrentAge()、getFather()和getMother()。图中也
有一些隐藏的属性和操作没有显示。
每个属性都有名字、类型和可见性级别。类型和可见性都是可选的。类型放在名字后面,
并用冒号进行分隔。可见性由前面的-、#、~或+指定,分别代表私有、受保护、包或公有
可见性。在图A1-1中,所有属性都是私有的,由前面的减号(-)指出。你也可以通过下划
线表示属性是否为静态属性或类属性。可以用可见性级别、带名字和类型的参数以及返回类型
来表示每个操作。
在类图中,名字设成斜体表示抽象的类或方法。例如,图A1-2中的Horse类就是抽象类。
通过在名字的上方添加短语“《interface》”(称为构造型)来指定接口。请看图A1-2中的
OwnedObject接口。也可以用空心圆来表示接口。
值得一提的是,表示类的图符可以有其他可选的部分。例如,处于类方框底层的第四部分
可以列出类的责任。在产生属性和操作之前,CRC卡片上列出的责任如能添加在UML图中类
方框的第4部分,则这一部分在CRC卡片(第6章)向类图转换时特别有用。本附录中的所有
图均未显示第4部分。
类图也可以表示类之间的关系。类和它的子类之间用实线加上空心的三角箭头连接。箭头
的 方 向 是 从 子 类 指 向 父 类 。 在 U M L 中 , 这 样 的 关 系 称 为 泛 化 。 比 如 , 在 图 A 1 - 2 中 , 类
Thoroughbred和类QuarterHorse显示为Horse抽象类的子类。带虚线的箭头表示接口的实现。在
UML中,这样的关系称为实现。例如,图A1-2中,Horse类实现了OwnedObject接口。
Thoroughbred
-father: Thoroughbred
-mother: Thoroughbred
-birthyear : int
+getFather(): Thoroughbred
+getMother(): Thoroughbred
+getCurrentAge(currentYear:Date): int
<< interface >>
OwnedObject
+getOwner().Person
* owner
Person
Horse
-name: String
+getName():String
Date
uses
Thoroughbred
QuarterHorse
图A1-1 Thoroughbred类的类图
图A1-2 有关马的类图
两个类之间的关联是指它们之间存在着结构上的关系。关联用实线表示,有很多可选部分。
可 以 在 它 的 每 一 端 都 加 上 标 签 , 指 定 关 联 中 每 个 类 的 角 色 。 例 如 , 在 图 A 1 - 2 中 ,
OwnedObject和Person之间存在关联,Person在此关联中扮演所有者(owner)的角色。关联线
的一端或两端有箭头表示可导航性。关联线的每一端也会有多重数值显示。可导航性和多重性
将在这一节的后面部分详细讲述。关联也可以通过循环连接它本身,这样的关联表明同一类所
创建的不同对象之间可以相互连接。
一端带箭头的关联表明这是一个单向导航。箭头表明从第一个类你可以很容易访问关联方
向所指的第二个类,但是从第二个类你却不能很容易地访问第一个类。关于这种现象的另外一
种解释是,第一个类可以察觉到第二个类,但是第二个类的对象将不能直接察觉到第一个类。
附录1 UML简介 609
没有箭头的关联通常表明它是一个双向的关联,这就是图A1-2中所指的。也有可能是仅仅意
味着可导航性并不重要,所以省略了。
应当注意到,一个类的某个属性和类(其属性所属的类型是类)的关联是一样的。就是说,
想表达类中的叫做“name”的String类型的特性,需要如同属性一样地显示它,如图A1-2中的
Horse类。或者,也可以构建一个从Horse类到String类的单向关联,在此关联中,String类的角
色是“name”。对于原始数据类型,用属性的办法会更好些,而当特性类在设计中起重要作用
时,用关联的方法通常比较好一些,在那种情况下,有那种类型的类方框更有价值。
依赖关系表示类之间的另一种连接,由一条虚线(可选的段末箭头和可选的标签)表示。
一个类依赖于另一个类,则改变另一个类也需要改变这个类。从一个类到另一个类的关联就自
动表明了一种依赖性。如果类之间已存在关联则不需要虚线。然而,对于短暂的关系(即一个
类不需要同另一个类维持长时间的连接,但确实偶尔会用到另一个类),我们应该从第一个类
画一条虚线到第二个类。例如,在图A1-2中,当Thoroughbred类的getCurrentAge()方法被调用
时,它需要使用Date类,所以依赖性被标识为“uses”。
关联一端的多重性是指类关联于其他类的对象的数量。多重性由非负整数或整数范围描述。
通过“0..1”描述的多重性是指在关联的一端存在0或1个对象。例如,世界上的每个人要么有
社会保险号,要么没有,因此,多重性0..1就可以在类图中的Person类和SocialSecurityNumber
类之间的关联中使用。由“1..*”描述的多重性是指一个或更多,由“0..*” 或只是“*”描述
的多重性是指0个或更多。在图A1-2中,与Person类关联的OwnedObject端的多重性使用了“*”,
因为Person可以拥有0个或更多的对象。
如果关联的一端有比1大的多重性,那么该端涉及的对象将可能被存储于收集中,如集合
或有序列表。在UML图中,也可以包括收集类本身,但是,由于关联的多重性,这样的类通
常被省略并假定存在那里。
聚合是一种特殊的关联,通过图符一端的空心钻石表示。它表明一种“整体/部分”关系,
箭头所指的类是关联的菱形端的一“部分”。组合表明聚合对部分的强所有权。在组合中,部
分随着所有者而生存或消亡,因为它们在独立于
所有者的软件系统中没有作用。请看图A1-3中
关于聚合和组合的例子。
College
Course
*
College有一个包含Building对象的聚合,这
表示建筑构成了学院。学院也有一个包含课程的
集合。如果学院倒闭了,建筑仍将存在(假定该
学院不是物理上消失)并可用于其他事情,但是
Course对象在学院之外则毫无用处,它是由学院提供的。如果学院作为一个事务实体不复存在
了,那么Course对象也就没用了,将不复存在。
图A1-3 College、Course和Buiding之间的关系
一定在某个Building中进行
*
Building
类图中另一个共同元素是注释,由具有狗耳角的方框表示,通过虚线连至其他图符。它可
有任意内容(文字和图形),类似于编程语言中的注释。它包括类的作用的解释或是该类的所
有对象应遵守的约束。如果内容是约束,内容外面将括着大括号。注意图A1-3中Course类所受
到的约束。
部署图
UML部署图关注软件系统的结构,用于显示软件系统在硬件平台和运行环境中的物理分
布。例如,设想你正在开发一个基于Web的图形显示包,包的用户将使用他们的Web浏览器访
610 附录1 UML简介
问你的网站,得到渲染信息。你的网站应根据用户的描述渲染图像并将其返回给用户。因为图
像渲染需要大量的计算,所以你决定将渲染从Web服务器中分离出来,放在一个单独的平台上。
这样,系统涉及3个硬件设备:Web客户端(运行浏览器的用户电脑),Web服务器所在的电脑
和渲染引擎所在的电脑。
图A1-4显示了此包的部署图。在此图中,
硬件部件放在标有“《device》”的方框中,硬
件部件之间的通信路径用带有可选标签的线表
示。在图A1-4中,路径是用连接设备的通信协
议和网络类型标记的。
部署图中的每个节点也用设备的细节注
释。例如,在图A1-4中,浏览器客户端被描述
为由Web浏览器软件构成的人造制品。人造制
品是指包含在设备上所运行软件的文件。你也
可以描述标记值,就像图A1-4中的Web服务器
节点一样。这些值定义了服务器所采用的Web
服务器厂家和服务器所使用的操作系统。
<
>
浏览器客户端
<>
Web浏览器
http/Internet
<>
Web服务器
{web server = apache}
{OS = linux}
http/LAN
<>
渲染引擎
图A1-4 部署图
部 署 图 也 可 以 显 示 运 行 环 境 节 点 , 将 运 行 环 境 节 点 绘 制 为 包 含 标 签 “《 e x e c u t i o n
environment》”的方框。这些节点表示可以运行其他软件的系统,如操作系统。
用例图
用例(第5、6章)和UML用例图可帮助你从用户的角度决定软件的功能和特点。为了让
读者了解用例和用例图是如何工作的,以下为数码音乐文件管理软件创建一些用例和用例图。
这个软件类似于Apple的iTunes软件。软件可能要做的一些事情包括:
• 下载MP3音乐文件,并将其存储于应用系统的存储库中。
• 捕捉流媒体音乐,并将其存储于应用系统的存储库中。
• 管理应用系统的存储库(例如,删除歌
曲或将其添加到播放列表中)。
• 将存储库中的歌曲清单刻录到CD上。
• 将 存 储 库 中 的 歌 曲 清 单 加 载 到 I P o d 或
MP3播放器。
• 将一首歌曲从MP3格式转换为AAC格式,
反之亦然。
这并不是一个全面的列表,但它已足够使
User
你理解用例和用例图的作用。
用例通过定义实现明确目标所需的步骤描
述了用户和系统之间的交互(例如,将歌曲清
单刻录到CD上)。一系列步骤的变动描述了各
种不同的场景(例如,如果歌曲清单中的所有
歌曲不适合放在一张CD上怎么办?)。
UML用例图是所有用例和用例之间关系的
视图。它提供了系统功能的整体图示。数码音
乐应用系统的用例图如图A1-5所示。
将音乐文件转
换为新格式
下载音乐文件并保
存到存储库中
捕捉流媒体音乐并
保存到存储库中
组织存储库
将歌曲清单刻录到CD上
将歌曲清单装载到iPod上
图A1-5 音乐系统的用例图
附录1 UML简介 611
在这个图中,木棍小人表示和其他类型的用户(或其他交互元素)相关联的参与者(第5
章)。复杂的系统通常不止一个参与者。例如,自动售货机应用系统可有3个参与者,表示客户、
维修人员和装货人员。
在用例图中,用例用椭圆形显示。角色通过线连接到所执行的用例上。注意,图中并不包
括用例的细节,用例的详细信息需要单独存储。另外,还需要注意,可将用例放在矩形框中,
而不能将角色放在矩形框中。矩形框表示的是系统的边界,而角色在系统之外。
系统的一些用例会互相关联,例如,将歌曲清单刻录到CD和将歌曲清单存储到iPod具有
相似的步骤。这两种情况,用户都会首先建立一个空表,然后再将存储库中的歌曲添加进来。
为避免用例中的重复,需建立新用例来表示重复活动,然后让其他用例包含这个新用例,作为
其他用例的一个步骤。在用例图中,如图A1-6所示,这种包含关系用标有《include》的虚线
箭头来连接用例和被包含的用例。
将音乐文件转换为新格式
下载音乐文件并保
存到存储库
捕捉流媒体音乐并
保存到存储库
组织存储库
User
<< include >>
将歌曲清单刻录到
CD上
<< include >>
编辑歌曲清单
将歌曲清单装载到
iPod上
<< include >>
图A1-6 具有包含用例的用例图
由于用例图显示了所有的用例,因此,用例图有助于确保覆盖系统的所有功能。在数码音
乐系统中,确实需要更多的用例,如播放库中歌曲的用例。但是请记住,用例在软件开发过程
中最有价值的地方是对每个用例的文字说明,而不是总体用例图[Fow04b]。通过用例的说明,
才能对所开发系统的目标形成清晰的理解。
顺序图
与类图和部署图不同,类图和部署图显示系统构件的静态结构,而顺序图显示任务执行过
程中对象之间的动态通信。它显示了完成任务的对象之间消息发出的先后顺序。顺序图可以显
示某个用例或软件系统的某个场景中存在的交互。
在图A1-7中,可以看到一个画图程序的顺序图。该图显示了在一幅图中点击一个图形时
612 附录1 UML简介
高亮度显示所涉及的步骤。图顶端行中的每个方框通常对应一个对象,虽然方框也有可能模拟
其他东西,比如类。如果方框表示对象(如我们所有例子中的情况),在方框内,可选地规定
冒号前的对象类型。也可在冒号之前写上类名,如图A1-7中第三个方框所示。在每个方框下
面都有一条被称为对象生命线的虚线。顺序图中的垂直轴代表着时间,随着时间逐渐增加,线
条逐渐向下移动。
顺序图使用从调用者到被调用者的水平箭头来表示方法调用,箭头上标有方法名称,可选
部分包括参数、参数的类型和返回类型。如图A1-7所示,MouseListener调用Drawing的
getFigureAt()方法。当对象在执行方法时(即在堆栈里有活动帧时),在对象的生命线下面可
选择性地显示一条空白的条,称为活动条。在图A1-7中,对于所有方法的调用都绘制了活动
条。图也可以通过虚线箭头和可选标记选择性地显示方法调用的返回结果。在图A1-7中,
getFigureAt()方法的返回结果由返回对象的名字标记。普遍的做法,如图A1-7所示,当一个无
返回结果的方法被调用时,将不会有返回箭头,因为这样将会使图变得杂乱,而且不会起任何
重要作用。带有箭头的黑圆圈表明一条来源未知或无关的发现消息。
:MouseListener
:Drawing
aFigure:Figure
:Graphics
.mouseClicked(point)
.getFigureAt(point)
aFigure
.highlight(graphics)
.setColor(red)
.drawRect (x,y,w,h)
.drawString(s)
图A1-7 一个顺序图的例子
读 者 现 在 应 该 能 够 理 解 图 A 1 - 7 显 示 的 任 务 了 。 未 知 源 调 用 M o u s e L i s t e n e r 中 的
m o u s e C l i c k e d ( ) 方法,将点击的点作为参数传入。 M o u s e L i s t e n e r 然后调用 D r a w i n g 的
getFigureAt()方法,并得到返回的一个Figure对象。接着MouseListener调用Figure的highlight()
方法,传递一个Graphics对象作为参数。作为响应,Figure调用Graphics对象的3个方法用红色
画出图形。
图A1-7比较简单,不包括附加条件和循环。若需逻辑控制结构,最好为每种情况都绘制
一张单独的顺序图。即当消息根据条件可有两条不同的路径时,则需要绘制两张分开的顺序图,
为每种可能性绘制一张。
若想要在一张顺序图上包括循环、条件和其他控制结构,可以使用交互框。交互框是矩形,
包围图的一部分,并用其所表示的控制结构的类型做标记。图A1-8描述了这种情况,高亮显
示 给 定 矩 形 中 所 有 图 形 所 涉 及 的 过 程 。 将 消 息 r e c t D r a g g e d 发 送 给 M o u s e L i s t e n e r ,
MouseListener通知绘图部分高亮显示矩形中的所有图形,具体做法是调用Drawing对象的
highlightFiguresIn()方法,并传递矩形作为参数。此方法要对Drawing对象中的所有Figure对象
附录1 UML简介 613
进行循环,如果Figure和矩形相交,则需要Figure高亮显示自身。在方括号内的短语称为守卫,
守卫是布尔条件,如果交互框中的动作要继续,则守卫必须为真。
:MouseListener
:Drawing
:Figure
.rectDragged(rect)
.highlight FiguresIn(rect)
loop ( )
[ for all Figures in the Drawing ]
opt
[ figure intersects
.highlight(g)
rect ]
图A1-8 带两个交互框的顺序图
顺序图还有很多其他特点。例如:
1. 可清楚地分辨出同步和异步消息。同步消息用实体箭头表示,而异步消息用棒形箭头
(stick arrowhead)显示。
2. 可用箭头表示对象向它本身发送消息。所用的
箭头需从该对象发出,然后折向下,再指回对象本身。
3. 通过绘制指向对象方框的带有适当标记(例如,
带有《create》标签)的箭头来表示对象的创建。这种
情况下,方框将出现在比行动开始时已存在对象对应
的方框低一些的位置。
4. 也可通过对象生命线末端的大写X显示对象的销
毁。其他对象可以销毁一个对象,在这种情况下,一
个箭头从其他对象指向X。X通常表示该对象已不再有
用,因此可以准备进行垃圾回收。
最后3个特点都显示在图A1-9所示的顺序图中。
通信图
:Thing1
.Thing2()
<>
:Thing2
.destroy()
x
.foo()
图A1-9 顺序图中的创建、销毁和循环
UML通信图(在UML1.x中称为“协作图”)提供了通信时间顺序的另一种表达形式,但
是强调对象和类之间的关系,而不是时间顺序。图A1-10所示的通信图与图A1-7中的顺序图显
示的是相同的动作。
在通信图中相互作用的对象由矩形表示。对象之间的关联由矩形之间连接的线表示。对于
图中启动消息传递序列的对象,通常有传入箭头指向该对象。箭头由数字和消息名称标记。如
果传入消息被标记为数字1并且它使接收对象调用其他对象的其他消息,则这些消息将沿关联
线从发送者到接收者的箭头表示,并按照它们被调用的顺序,标以数字1.1、1.2等。如果这些
消息又调用了其他消息,另外的十进制小数点和数字将被添加到标记这些消息的数字中,说明
消息传递的进一步嵌套。
614 附录1 UML简介
在图A1-10中,可以看到mouseClicked消息调用getFigureAt()方法,然后又调用highlight()
方法。highlight()消息调用其他3个消息:
setColor()、drawRect()和drawstring()。每个
标签上的数码编号就像每条消息的时序性
质那样显示嵌套。
有很多可选特点被添加进箭头标记中。
例如,可以在数字前面添加一个字母。传
入箭头可以标记为A1:mouseClicked(point),
指明可执行线程A。如果其他消息在其他线
程中执行,它们的标记前面将会是一个不
同的字母。例如,如果mouseClicked()在线
程A中可执行,但是它创建了一个新线程B,
并且调用该线程中的highlight(),那么从
MouseListener到Figure的箭头将被标记为
1.B2:highlight(graphics)。
1: mouseClicked(point)
1.1: getFigureAt(point)
1.2: highlight(graphics)
MouseListener
Drawing
Figure
1.2.1: setColor(red)
1.2.2: drawRect(x,y,w,h)
1.2.3: drawString(s)
Graphics
图A1-10 UML通信图
如果对显示对象之间的关系及对象间传递的消息感兴趣,通信图可能是比顺序图更好的选
择。如果对命令传递的时间顺序感兴趣,那么顺序图也许更好。
活动图
UML活动图通过系统所执行动作之间的控制流来描述系统或部分系统的动态行为。它类
似于流程图,但活动图可以显示并行流。
活动图的主要构件是动作节点,由圆角
矩形表示,对应于软件系统执行的任务。
从一个动作节点到另一个动作节点的箭头
表示控制流。也就是说,在两个动作节点
之间的箭头意味着第一个动作完成后,第
二个动作才开始。实心黑点表示活动开始
的初始节点。被黑圆圈包围的黑点表示活
动结束的最终节点。
分叉表示活动分为两个或更多并行活
动,被绘制成水平黑条,并带有一个指向
自己的箭头、两个或更多出来的箭头。每
个发出的箭头都代表一个控制流,此控制
流可与其他发出的箭头所对应的控制流并
行执行。这些并行活动可在一台电脑上使
用不同的线程执行,甚至使用不同的电脑
执行。
图A1-11显示了一个烤蛋糕的样本活动
图。第一步是寻找食谱。一旦找到了食谱,
就可以称量和搅拌干原料和湿原料,并且
可以预热烤箱。干原料的搅拌可与湿原料
寻找食谱
搅拌干原料
搅拌湿原料
烤箱加热
搅拌到一起
烘烤
(not done)
(done)
从烤箱里取出
图A1-11 烤蛋糕的UML活动图