为 了理解UML,需要形成该语言的概念模型,这要求学习建模的3个要素:UML的基本构造块、支配这些构造块如何放在一起的规则和一些运用于整个UML的公 共机制。如果掌握了这些思想,就能够读懂UML模型,并能建立一些基本模型。当有了较丰富的应用UML的经验时,就能够在这些概念模型之上使用更高深的语 言特征进行构造。 2.2.1 UML的构造块 UML的词汇表包含下面3种构造块: (1)事物 (2)关系 (3)图 事物是对模型中首要成分的抽象;关系把事物结合在一起;图聚集了相关的事物。 1. UML中的事物 在UML中有4种事物: (1)结构事物 (2)行为事物 (3)分组事物 (4)注释事物 这些事物是UML中基本的面向对象的构造块,用它们可以写出结构良好的模型。 2. 结构事物 结构事物(structural thing)是UML模型中的名词。它们通常是模型的静态部分,描述概念元素或物理元素。结构事物总称为类目(classifier)。 第一,类(class)是对一组具有相同属性、相同操作、相同关系和相同语义的对象的描述。类实现一个或多个接口。在图形上,把类画成一个矩形,矩形中通常包括类的名称、属性和操作,如图2-1所示。 图2-1 类 第二,接口(interface)是一组操作的集合,每个操作描述了类或构件的一个服务。因此,接口描述了元素的外部可见行为。一个接口可以描述一个类或 构件的全部行为或部分行为。接口定义了一组操作规约(即操作的特征标记),而不是操作的实现。接口的声明看上去是在名称的上方标注着关键 字?interface?的类;除非有时用来表示常量,否则不需要属性。然而,接口很少单独出现。如图2-2所示,把由类提供的对外接口表示成用线连接到 类框的一个小圆圈,把类向其他类请求的接口表示成用线连接到类框的半个小圆圈。 ![](https://i-blog.csdnimg.cn/blog_migrate/f722d7102a41c38d36ca662e32a5822c.jpeg) 图2-2 接口 第三,协作(collaboration)定义了一个交互,它是由一组共同工作以提供某种协作行为的角色和其他元素构成的一个群体,这些协作行为大于所有 元素的各自行为的总和。协作具有结构、行为和维度。一个给定的类或对象可以参与几个协作。这些协作因而表现了系统构成模式的实现。在图形上,把协作画成虚 线椭圆,有时仅包含它的名称,如图2-3所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/f73b35d4d9eb10399861a06b7cdf32e0.jpeg) 图2-3 协作 第四,用况(use case)是对一组动作序列的描述,系统执行这些动作将产生对特定的参与者有价值而且可观察的结果。用况用于构造模型中的行为事物。用况是通过协作实现的。在图形上,把用况画成实线椭圆,通常仅包含它的名称,如图2-4所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/9b55a04cb1163f26dfabdf7878969b0b.jpeg) 图2-4 用况 剩余的3种事物——主动类、构件和结点,都和类相似,就是说它们也描述了一组具有相同属性、相同操作、相同关系和相同语义的实体。然而,这3种事物与类的不同点也不少,而且对面向对象系统的某些方面的建模是必要的,因此对这几个术语需要单独处理。 第 五,主动类(active class)是这样的类,其对象至少拥有一个进程或线程,因此它能够启动控制活动。主动类的对象所表现的元素的行为与其他元素的行为并发,除了这一点之 外,它和类是一样的。在图形上,把主动类绘制成类图符,只是它的左右外框是双线,通常它包含名称、属性和操作,如图2-5所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/531e8c781d3c38363e863381b2994864.jpeg) 图2-5 主动类 第六,构件(component)是系统设计的模块化部件,将实现隐藏在一组外部接口之后。在一个系统中,共享相同接口的构件可以相互替换,只要保持相同 的逻辑行为即可。可以通过把部件和连接件接合在一起表示构件的实现;部件可以包括更小的构件。在图形上,构件的表示很像类,只是在其右上角有一个特殊的图 标,如图2-6所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/79ba422ffe0ab8b0fa14d420431e11a5.jpeg) 图2-6 构件 剩下的两种元素是制品和结点,它们也是不同的。它们表示物理事物,而前6种元素表示概念或逻辑事物。 第七,制品(artifact)是系统中物理的而且可代替的部件,它包括物理信息(“比特”)。在一个系统中,会遇到不同类型的部署制品,如源代码文件、 可执行程序和脚本。制品通常代表对源码信息或运行时信息的物理打包。在图形上,把制品画成一个矩形,在其名称的上方标注着关键字?artifact?,如 图2-7所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/169a19bb416bee78e40726379c6d2dab.jpeg) 图2-7 制品 第八,结点(node)是在运行时存在的物理元素,它表示一个计算机资源,通常至少有一些记忆能力和处理能力。一组构件可以驻留在一个结点内,也可以从一个结点迁移到另一个结点。在图形上,把结点画成一个立方体,通常在立方体中只写它的名称,如图2-8所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/84faa4b9b4d44518f1e6e5d9e451734b.jpeg) 图2-8 结点 这些元素——类、接口、协作、用况、主动类、构件、制品和结点,是UML模型中可以包含的基本结构事物。它们也有变体,如参与者、信号、实用程序(一种类)、进程和线程(两种主动类)、应用、文档、文件、库、页和表(一种制品)等。 3. 行为事物 行为事物(behavioral thing)是UML模型的动态部分。它们是模型中的动词,代表了跨越时间和空间的行为。共有3类主要的行为事物。 第一,交互(interaction)是这样一种行为,它由在特定语境中共同完成一定任务的一组对象或角色之间交换的消息组成。一个对象群体的行为或者单 个操作的行为可以用一个交互来描述。交互涉及一些其他元素,包括消息、动作和连接件(对象间的连接)。在图形上,把消息画成一条有方向的直线,通常在其上 总是带有操作名,如图2-9所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/3e6f655af609bf9d6d129e10839464d8.jpeg) 图2-9 消息 第 二,状态机(state machine)是这样一种行为,它描述了一个对象或一个交互在生命期内响应事件所经历的状态序列以及对这些事件的响应。单个类或一组类之间协作的行为可 以用一个状态机来描述。状态机涉及到一些其他元素,包括状态、转移(从一个状态到另一个状态的流)、事件(触发转换的事物)和活动(对一个转移的响应)。 在图形上,把状态画成一个圆角矩形,通常在其中含有状态的名字及其子状态(如果有的话),如图2-10所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/82d60e630b6795f064860adb559ca4d3.jpeg) 图2-10 状态 第三,活动(activity)是这样一种行为,它描述了计算过程执行的步骤序列。交互所注重的是一系列相互作用的对象,状态机所注重的是一定时间内一个 对象的生命周期,活动所注重的是步骤之间的流而不关心哪个对象执行哪个步骤。活动的一个步骤称为一个动作。在图形上,把动作画成一个圆角矩形,在其中含有 指明其用途的名字。状态和动作靠不同的语境得以区别,如图2-11所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/5b9c22fb7dd00183574f3b2fdddef3bc.jpeg) 图2-11 动作 交互、状态机和活动这三种元素是可以包含在UML模型中的基本行为事物。在语义上,这些元素通常与各种结构元素(主要是类、协作和对象)相关。 4. 分组事物 分组事物(grouping thing)是UML模型的组织部分。它们是一些由模型分解成的“盒子”。主要的分组事物是包。 包(package)是用于对设计本身进行组织的通用机制,与类不同,类是用来组织实现构造物。结构事物、行为事物甚至其他的分组事物都可以放进包内。包 不像构件(构件在运行时存在),它纯粹是概念上的(即它仅在开发时存在)。在图形上,把包画成带标签的文件夹(一个左上角带有一个小矩形的大矩形),在矩 形中通常仅含有包的名称,有时还含有其内容,如图2-12所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/e95ab8d3df276008df3cb577ecf540e8.jpeg) 图2-12 包 包是用来组织UML模型的基本分组事物。它也有变体,如框架、模型和子系统(它们是包的不同种类)。 5. 注释事物 注 释事物(annotational thing)是UML模型的解释部分。这些注释事物用来描述、说明和标注模型的任何元素。有一种主要的注释事物,称为注解。注解(note)是依附于一个 元素或一组元素之上对其进行约束或解释的简单符号。在图形上,把注解画成一个右上角是折角的矩形,其中带有文字或图形解释,如图2-13所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/5374388b902837b13892665480475681.jpeg) 图2-13 注解 该元素是可以包含在UML模型中的基本注释事物。通常可以用注解中所含的约束或解释来修饰图,当然最好是把注释表示成形式或非形式化的文本。这种元素也有变体,如需求(从模型的外部来描述一些想得到的行为)。 6. UML中的关系 在UML中有4种关系: (1)依赖 (2)关联 (3)泛化 (4)实现 这些关系是UML的基本关系构造块,用它们可以写出结构良好的模型。 第一,依赖(dependency)是两个模型元素间的语义关系,其中一个元素(独立元素)发生变化会影响另一个元素(依赖元素)的语义。在图形上,把依赖画成一条可能有方向的虚线,偶尔在其上还带有一个标记,如图2-14所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/62e0bed6d001d66ecb9665a821880b8c.jpeg) 图2-14 依赖 第二,关联(association)是类之间的结构关系,它描述了一组链,链是对象(类的实例)之间的连接。聚合是一种特殊类型的关联,它描述了整体和 部分间的结构关系。在图形上,把关联画成一条实线,它可能有方向,偶尔在其上还带有一个标记,而且它还经常含有诸如多重性和端名这样的修饰,如图2-15 所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/6f5a14843c67b212d1498bf910f8d64d.jpeg) 图2-15 关联 第三,泛化(generalization)是一种特殊/一般关系,在其中特殊元素(子元素)基于一般元素(父元素)而建立。用这种方法,子元素共享了父元素的结构和行为。在图形上,把泛化关系画成一条带有空心箭头的实线,该实线指向父元素,如图2-16所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/c56bc86930cf6b3de49915e3d93c6954.jpeg) 图2-16 泛化 第四,实现(realization)是类目之间的语义关系,其中的一个类目指定了由另一个类目保证执行的合约。在两种地方会遇到实现关系:一种是在接口 和实现它们的类或构件之间;另一种是在用况和实现它们的协作之间。在图形上,把实现关系画成一条带有空心箭头的虚线,它是泛化和依赖关系两种图形的结合, 如图2-17所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/08e1e0aa7dbf0d95a7127f21f2033790.jpeg) 图2-17 实现 这4种元素是UML模型中可以包含的基本关系事物。它们也有变体,例如,精化、跟踪、包含和扩展。 7. UML中的图 图(diagram)是一组元素的图形表示,大多数情况下把图画成顶点(代表事物)和弧(代表关系)的连通图。为了对系统进行可视化,可以从不同的角度画 图,这样图是对系统的投影。对所有的系统(除非很微小的系统)而言,图是系统组成元素的省略视图。有些元素可以出现在所有图中,有些元素可以出现在一些图 中(很常见),还有些元素不能出现在图中(很罕见)。在理论上,图可以包含事物及其关系的任何组合。然而,实际上仅出现少量的常见组合,它们要与组成软件 密集型系统的体系结构的5种最有用的视图相一致。由于这个原因,UML包括13种这样的图: (1)类图 (2)对象图 (3)构件图 (4)组合结构图 (5)用况图 (6)顺序图 (7)通信图 (8)状态图 (9)活动图 (10)部署图 (11)包图 (12)定时图 (13)交互概览图 类图(class diagram)展现了一组类、接口、协作和它们之间的关系。在面向对象系统的建模中所建立的最常见的图就是类图。类图给出系统的静态设计视图。包含主动类的类图给出系统的静态进程视图。构件图是类图的变体。 对象图(object diagram)展现了一组对象以及它们之间的关系。对象图描述了在类图中所建立的事物的实例的静态快照。和类图一样,这些图给出系统的静态设计视图或静态进程视图,但它们是从真实案例或原型案例的角度建立的。 构 件图(component diagram)展现了一个封装的类和它的接口、端口以及由内嵌的构件和连接件构成的内部结构。构件图用于表示系统的静态设计实现视图。对于由小的部件构 建大的系统来说,构件图是很重要的。(UML将构件图和适用于任意类的组合结构图区分开来,但由于构件和结构化类之间的差别未必是细微的,所以一起讨论它 们。) 用况图(use case diagram)展现了一组用况、参与者(一种特殊的类)及它们之间的关系。用况图给出系统的静态用况视图。这些图在对系统的行为进行组织和建模上是非常重要的。 顺 序图和通信图都是交互图。交互图(interaction diagram)展现了一种交互,它由一组对象或角色以及它们之间可能发送的消息构成。交互图专注于系统的动态视图。顺序图(sequence diagram)是强调消息的时间次序的交互图;通信图(communication diagram)也是一种交互图,它强调收发消息的对象或角色的结构组织。顺序图和通信图表达了类似的基本概念,但每种图强调概念的不同视图,顺序图强调 时序,通信图强调消息流经的数据结构。定时图(不包含在本书中)展现了消息交换的实际时间。 状态图(state diagram)展现了一个状态机,它由状态、转移、事件和活动组成。状态图展现了对象的动态视图。它对于接口、类或协作的行为建模尤为重要,而且它强调事件导致的对象行为,这非常有助于对反应式系统建模。 活动图(activity diagram)将进程或其他计算的结构展示为计算内部一步步的控制流和数据流。活动图专注于系统的动态视图。它对于系统的功能建模特别重要,并强调对象间的控制流程。 部署图(deployment diagram)展现了对运行时的处理结点以及在其中生存的构件的配置。部署图给出了体系结构的静态部署视图。通常一个结点包含一个或多个制品。 制品图(artifact diagram)展现了计算机中一个系统的物理结构。制品包括文件、数据库和类似的物理比特集合。制品常与部署图一起使用。制品也展现了它们实现的类和构件。(UML把制品图视为部署图的变体,但我们分别地讨论它们。) 包图(package diagram)展现了由模型本身分解而成的组织单元以及它们的依赖关系。 定时图(timing diagram)是一种交互图,它展现了消息跨越不同对象或角色的实际时间,而不仅仅是关心消息的相对顺序。交互概览图(interaction overview diagram)是活动图和顺序图的混合物。这些图有特殊的用法,本书不做讨论,更多的细节可参考The Unified Modeling Language Reference Manual。 并不限定仅使用这几种图,开发工具可以利用UML来提供其他种类的图,但到目前为止,这几种图在实际应用中是最常用的。 2.2.2 UML规则 不能简单地把UML的构造块按随机的方式堆放在一起。像任何语言一样,UML有一套规则,这些规则描述了一个结构良好的模型看起来应该像什么。结构良好的模型应该在语义上是自我一致的,并且与所有的相关模型协调一致。 UML有自己的语法和语义规则,用于: ◎ 命名 为事物、关系和图起的名字 ◎范围 使名字具有特定含义的语境 ◎可见性 这些名字如何让其他成分看见和使用 ◎完整性 事物如何正确、一致地相互联系 ◎执行 运行或模拟动态模型的含义是什么 在软件密集型系统的开发期间所建造的模型往往需要发展变化,并可以由许多人员以不同的方式、在不同的时间进行观察。由于这个原因,下述的情况是常见的,即开发组不但会建造一些结构良好的模型,也会建造一些这样的模型: ◎省略 隐藏某些元素以简化视图 ◎不完全 可能遗漏了某些元素 ◎不一致 不保证模型的完整性 在软件开发的生命期内,随着系统细节的展开和变动,不可避免地要出现这些不太规范的模型。UML的规则鼓励(不是强迫)专注于最重要的分析、设计和实现问题,这将促使模型随着时间的推移而具有良好的结构。 2.2.3 UML中的公共机制 通过与具有公共特征的模式取得一致,可以使一座建筑更为简单和更为协调。房子可以按一定的结构模式(它定义了建筑风格)建造成维多利亚式的或法国乡村式的。对于UML也是如此。由于在UML中有4种贯穿整个语言且一致应用的公共机制,因此使得UML变得较为简单。这4 种机制是: (1)详述 (2)修饰 (3)通用划分 (4)扩展机制 1. 详述 UML不仅仅是一种图形语言。实际上,在它的图形表示法的每部分背后都有一个详述,这个详述提供了对构造块的语法和语义的文字叙述。例如,在类的图符背后 有一个详述,它提供了对该类所拥有的属性、操作(包括完整的特征标记)和行为的全面描述;在视觉上,类的图符可能仅展示了这个详述的一小部分。此外,可能 存在着该类的另一个视图,其中提供了一个完全不同的部件集合,但是它仍然与该类的基本详述相一致。UML的图形表示法用来对系统进行可视化;UML的详述 用来说明系统的细节。假定把二者分开,就可能进行增量式的建模。这可以通过以下方式完成:先画图,然后再对这个模型的详述增加语义,或直接创建详述,也可 能对一个已经存在的系统进行逆向工程,然后再创建作为这些详述的投影的图。 UML的详述提供了一个语义底版,它包含了一个系统的各个模型的所有部分,各部分以一致的方式相互联系。因此,UML的图只不过是对底版的简单视觉投影,每一个图展现了系统的一个特定的关注方面。 2. 修饰 UML中的大多数元素都有唯一的和直接的图形表示符号,这些图形符号对元素的最重要的方面提供了可视化表示。例如,特意把类的符号设计得容易画出,这是因 为在对面向对象系统建模中,类是最常用的元素;类的图形符号也展示了类的最重要方面,即它的名称、属性和操作。【第6章讨论注解和其他修饰。】 对类的详述可以包含其他细节,例如,它是否是抽象类,或它的属性和操作是否可见。可以把很多这样的细节表示为图形或文字修饰,放到类的基本矩形符号上。例 如,图2-18表示的是一个带有修饰的类,图中表明这个类是一个抽象类,有两个公共操作、一个受保护操作和一个私有操作。 ![](https://i-blog.csdnimg.cn/blog_migrate/1da3062a410270aaf2f2ae89af22b195.jpeg) 图2-18 修饰 UML表示法中的每一个元素都有一个基本符号,可以把各种修饰细节加到这个符号上。 3. 通用划分 在对面向对象系统建模中,通常有几种划分方法。 第一种方法是对类和对象的划分。类是一种抽象,对象是这种抽象的一个具体表现。在UML中,可以对类和对象建立模型,如图2-19所示。在图形上,UML是这样辨别对象的:用与类同样的图形符号来表示对象,并且在对象名的下面画一道线。 ![](https://i-blog.csdnimg.cn/blog_migrate/0e4ea0e154946b5bb039a7bbe55b6b4f.jpeg) 图2-19 类和对象 在这个图中,有一个名称为Customer的类,它有3个对象,分别为Jan(它被明确地标记为Customer的对象),:Customer(匿名的 Customer对象)和Elyse(它在详述中被说明为是一种Customer对象,尽管在这里没有明确地表示出来)。 UML的每一个构造块几乎都存在像类/对象这样的二分法。例如,可以有用况和用况执行、构件和构件实例、结点和结点实例等。 第二种方法是接口和实现的分离。接口声明了一个合约,而实现则表示了对该合约的具体实施,它负责如实地实现接口的完整语义。在UML中,既可以对接口建模又可以对它们的实现建模,如图2-20所示。 ![](https://i-blog.csdnimg.cn/blog_migrate/c5a9c2838c58d3cb0374f9ef7e3778bc.jpeg) 图2-20 接口和实现 在这个图中,有一个名称为SpellingWizard.dll的构件,它实现了接口IUnknown和接口ISpelling,并且还需要一个由其他构件提供的名为IDictionary的接口。 几乎每一个UML的构造块都有像接口/实现这样的二分法。例如,用况和实现它们的协作,操作和实现它们的方法。 第三种方法是类型和角色的分离。类型声明了实体的种类(如对象、属性或参数),角色描述了实体在语境中的含义(如类、构件或协作等)。任何作为其他实体结 构中的一部分的实体(例如属性)都具有两个特性:从它固有的类型派生出一些含义,从它在语境中的角色派生出一些含义(如图2-21所示)。 ![](https://i-blog.csdnimg.cn/blog_migrate/ebe461318929c1ba201085e26e2a17e3.jpeg) 图2-21 具有角色和类型的部件 4. 扩展机制 UML提供了一种绘制软件蓝图的标准语言,但是一种闭合的语言即使表达能力再丰富,也难以表示出各种领域中的各种模型在不同时刻所有可能的细微差别。由于这个原因,UML是目标开放的,使人们能够以受控的方式来扩展该语言。UML的扩展机制包括: ◎衍型 ◎标记值 ◎约束 衍型(stereotype)扩展了UML的词汇,可以用来创造新的构造块,这个新构造块既可从现有的构造块派生的,又专门针对要解决的问题。例如,假设 正在使用一种编程语言,如Java或C++,经常要对“异常事件”建模。在这些语言里,“异常事件”就是类,只是用很特殊的方法进行了处理。通常可能只想 允许抛出和捕捉异常事件,没有其他要求。此时可以让异常事件在模型中成为“一等公民”——可以像对待基本构造块一样对待它们,只要用一个适当的衍型来标记 它们即可。请看图2-22中的类Overflow。 【第6章讨论UML的扩展机制。】 ![](https://i-blog.csdnimg.cn/blog_migrate/209f4f65b9bbef159f2a252c625f3768.jpeg) 图2-22 扩展机制 标 记值(tagged value)扩展了UML衍型的特性,可以用来创建衍型的详述的新信息。例如,如果在制作以盒装形式销售的产品,随着时间的推移,它经过了多次发行,那么 经常会想要跟踪产品的版本和对产品做评论性摘要的作者。版本和作者不是UML的基本概念,通过引入新的标记值,可以把它们加到像类那样的任何构造块中去。 例如,在图2-22中,在类EventQueue上明确标记了版本和作者,这样就对该类进行了扩展。 约束(constraint)扩展了UML构造块的语义,可以用来增加新的规则或修改现有的规则。例如,可能想约束类EventQueue,以使所有的增加都按序排列。如图2-22所示,对操作add增加了一个约束,即{ordered},以明确标示这一规则。 总的来说,这3种扩展机制允许根据项目的需要塑造和培育UML。这些机制也使得UML适合于新的软件技术(例如,很可能出现的功能更强的分布式编程语 言)。可以增加新的构造块,修改已存在的构造块的详述,甚至可以改变它们的语义。当然,以受控的方式进行扩展是重要的,这样可不偏离UML的真正目的—— 信息交流。 原文如此。UML2.0规范文本介绍的结点表示法可以画成一个长方体,其中除了必须有结点的名字之外还可以包含部署于其上的制品。——译者注 将sequence diagram译为顺序图,是本书极个别与国标不一致之处。在制定国标GB/T 11457-2006时,对这种图的名称有“顺序图”和“时序图”两种不同意见,最后定为“时序图”。但是后来UML2.0又定义了另外一种图,即 timing diagram,而国内的其他标准又把这种新的图译为“时序图”。于是这两种图的中文译名发生了冲突。为了避免由此引起的术语混乱,本书将它们分别译为 “顺序图”和“定时图”。——译者注 |