216.多继承(multiple inheritance)
泛化的一种语义变体,其中元素可以有多个父。这是U/NL 中的默认设置,在多数情况下是必须的,建模者也可以对使用的元素进行某种设置。对比:单继承。
217.多重性(multiplicity)
说明允许侯选值范围,如集合可以设定的大小。多重性说明可能用于关联端、组成类中的部分、消息的迭代次数和其他目的等。本质上讲,多重性是非负整数的一个子集(可能无限)。对比:集合的基数。
见关联的多重性(multiplicityof association)、类的多重性(multiplicity of class)。
语义
多重性是对集合大小的说明。概念上,它是非负整数的子集。实际上,它是一个有限的整数集合,是最大值和最小值之间的区域。任何集合必须有限,但上界可以是有限值或者无界(无界的多重性称为"许多")。上界必须大于0;否则多重性就为0。0多重性的用处不大,因为它仅允许空集。多重性用字符串表示。
通常,多重性是一个整数范围--有最大值和最小值。但它通常又是不连续的非负整数的集合。整数集合可能是无限的--即上界可能无限(但集合中的每个特定基数是有限的)。
在实际中,这一整数集合可以声明为几个互斥,不相连的整数区域。区域是指最大值和最小值之间的连续的整数。有些无限集合不能这样表示,如偶数集合,但这种简化表示不会丢失太多信息。设计中,通常只用有上下限的一个整数区域来描述多重性,因为多重性只用于定义可能需要的最大存储空间。
见关联的多重性和类的多重性,以进一步了解这些元素多重性的使用细节。
表示法
多重性表示为用逗号隔开的整数区域列表的文本形式,区域格式为:
最小值..最大值
其中最小值和最大值是整数,或者最大值为"*",表示无上界。表达式2..*读做"两个或以上"。
区域的格式还可以为:
数字
数字是表示单个大小区域的整数。
包含单个星的多重性表达式
*
与0..*等价,表示不限制数目("0个或多个,无限制")。这种常见的多重性被称为"许多"。
举例
0..1
1
0..*
*
1..*
1..6
1..3,7,10,15,19..*
风格指南
* 建议使用递增顺序的区域。如:1..3,7,10比7,10,1..3好。
* 2个相连的区域被连成1个。例如0..1比0,1好。
讨论
多重性表达式可以含有变量,但模型完成后必须替换为整数--必须是参数或常数。多重性与动态数组边界不同,在运行时不能改变。它用于说明集合中可能出现的值的范围(最坏情况),应用程序的数据结构和操作应与之相符合。它是建模时的常数,如果运行时边界可变,应选的多重性为"许多"(0..*)。
图中可能省略多重性,但它隐含存在于模型中。完成的模型里,未说明的多重性没有意义。不知道多重性和将它声明为"许多"是一样的,因为此时的待选值可以有任意多个,这与"许多"的定义一样。
见未说明的值(unspecified value)。
218.关联的多重性(multiplicity of association)
关联端声明的多重性。
见多重性(multiplicity)。
语义
定义在关联端的多重性,说明该位置上可以有多少个对象。
对于二元关联,目标端的多重性限制了源端的一个对象可以与目标类的多少个对象之间有关联。多重性作为一个整数区域给出(见多重性)。常见的多重性有1、0或1、0个或多个无限制、1个或多个无限制。"0个或多个无限制"被称为"许多"。
n元关联中,多重性在每个n-1维端上定义。例如,给定类(A,B,C)之间的三元关联,C端的多重性分别说明C可以有多少个对象参与A和B的关联。如果多重性为(许多,许多,1)则对每个(A,B)对,只有一个C值;对每个(B,C)对可以有许多个A值,但A、B、C的许多值可以参与关联。
见n元关联中对n维多重性的讨论。
表示法
多重性标注在使用它的路径边上
(图13-126)数字范围n1..n2。
见多重性,以进一步了解语法和规范说明(可能比多数实际应用所需的内容更广泛)。
219.(属性的)多重性(multiplicity (of attribute))
每个对象可能有的属性值。
语义
属性的多重性说明有该属性的对象可以有多少个值。
常见的多重性为(1..1),即每个对象的属性有1个值,其他还有0或1(可选或空值)、0个或多个无限制(值的集合)、1个或多个无限制(非空集合)。"0个或多个,无限制"称为"许多"。
表示法
多重性标在分格中的属性名字之后的括号中,后面有冒号(图13-127),如果没有标出,多重性就为1(默认值)。
220.(类的)多重性(multiplicity (of class))
类的实例可能的数目范围--同时可以存在多少个实例。
语义
对于类,多重性说明类可以有多少个实例,默认值是无限多个,但有时确定数目也很有用。特别是在声明单个类--只有1个实例的类时,需要用多重性建立整个系统的内容和参数。
合作中也用到类的多重性,它说明类元角色在一个合作实例中可以有多少绑实例。
表示法
类或类元的多重性是标在矩形右上角的字符串(图13-128)。多重性为许多(无限)时,字符串可以省略。图13-128 类的多重性
221.n元关联(n-ary association)
3个以上类之间的关联。对比:二元关联。
语义
每个关联的实例是来自于相应类的n元组值。一个类可以在关联的多个位置中出现。二元关联是一种特例,有简化的表示法和特有的属性(如导航性),这些属性对n元关联没有意义(至少是相当复杂)。
n元关联可以声明多重性,但不像二元关联那么容易理解。关联端的多重性说明了当另外n-1端的值确定时,本端值的数目。这种定义也适用于二元关联。
聚集(包括组成)只对二元关联有意义,n元关联的角色不能有组成或聚集。
二元关联和只有两端的n元关联没有什么语义区别。有2端的关联被认为是二元关联,有两个以上端的关联被视为n元关联。
表示法
n元关联表示为一个大菱形(大是相对路径端点而言),以及由菱形引出通向各个参与类的路径。关联的名字(如果有),标在菱形边上。修饰与二元关联一样标在每条路径的端点上。可以有多重性,但不能有资格限定和聚集。
可以用虚线将关联类符号与菱形符号相连,以此表示有属性、操作和/或关联的n元关联。
举例
图13-129表示一支球队每个赛季的最高记录保持者。记录保持者在赛季期间可以转会,在其他队中留下记录。记录本上,每个连接是独立的。
风格指南
通常,线从菱形顶点或某边的中点开始画。
讨论
n元关联中,多重性的定义是按其他n-1维进行的。例如,类之间的三元关联(A,B,C),C端的多重性说明 C与每个A、B对之间的关联中可以有多少个C对象。如果多重性为(许多,许多,1),则对每个可能的(A,B)对只有一个C值。对给定的一个(B,C)对,可以有多个A值。A,B,C各自的许多值参与关联。二元关联中,定义简化为一个关联端对另一端的多重性。
只对一端定义多重性没有意义(正如某些作者所提议)。因为对任何有意义的n元关联端,多重性都是许多。否则,n元关联可以化简为一个类和一个包含其他类的关联类之间的二元关联,这样更容易实现。因为二元关联更易实现,且宜导航,最好避免n元关联。只有当需要所有值来确定一条连接时,n元关联才有用。通常,n元关联实现为一个类,类的属性中含有指向参与对象的指针。将它表示元关联是因为关联中没有迭代的连接。
考虑学生在学期之内选修某个教授的课程的例子(图13-130)。
学生不会多次选修一个教授的同一门课程,但是可以从同一名教授处选修几门不同的课程。一个教授可以教多门课程。图中表示了多重性。Professor的多重性是(0..1),其他多重性是许多(0..*)。
每个多重性值是相对于其他端对象对而言。对于(课程,学生)对,可以有0个或1个教授。对(学生,教授)对,可以有许多课程。对(课程,教授)对,有许多学生。
注意:如果关联化为类,就可能有多个相同(学生,教授,课程)组成,这是不希望出现的情况。
222.名字
用于标识模型元素的字符串。
见命名空间(namespace)。
语义
名字是一种标识符--用某种程序设计语言预先定义的有限的字符序列。实现方法可以规定名字的格式,例如不得包含某种符号(如标点符号),还可以规定初始规则等等。特别是,认为名字是在不同数据集合中可以用于查找、搜索的主键。例如,罗马字体通常有大写和小写、数字、分隔符(如下划线连字符),而其他标点符号依赖于具体实现。
工具和程序设计语言可以规定名字的长度和使用的字符范围,这些限制比对于注释的限制更严格。
名字是在命名空间内定义的,如包或者类。命名空间中,名字在其所在的语义组内必须是唯一的,如类元、状态、属性等;不同组内的名字可以迭代(但是也应该避免)。每个命名空间属于更大的命名空间。嵌套的名字及其外部名字以至最外层元素的名字可以用一个名字路径串表示。
表示法
名字表示为字符串。名字通常单独列为一行。规范的名字格式包括字符、数字、下划线。如果某个实现允许其他字符,则某些字符可能要编码显示以防止混淆。这是工具实现的责任。
用双斜线分隔的不同层次命名空间的名字可以构成路径名。
223.命名空间(namespace)
模型的一部分,名字在此处定义并使用。命名空间内,每个名字有特有的意义。
语义
所有有名字的元素都在命名空间内声明,它们名字的范围也是该命名空间。顶级的命名空间是包(包含子系统)或者包含者,包含者的目的主要是将元素组织为易于人类理解并访问的组,并在开发中将模型组成为易于计算机存储、维护的组。基本的模型元素,包括类、关联、状态机、合作都是它们各自内容(如属性、关联端、状态机、合作角色)的命名空间。每个模型元素的范围在各自的介绍中说明。每种模型元素有各自的命名空间。
命名空间内定义的名字必须唯一(这正是使用名字的目的)。给出命名空间和名字,可以找到具体的模型元素(如果它有名字--有些元素是匿名的,必须通过有名字的元素与它的关联来查找)。命名空间可以嵌套,给出嵌套的命名空间名称,就可以向内查找。
包可以访问或者导入另一个包,从而访问它的命名空间。
系统自身定义了最外层的命名空间,它是所有名字的基础。它是一个包,通常还带有几层嵌套的包,直到得到最终基本元素的名字为止。
表示法
路径名(穿过几个嵌套命名空间的路径)的表现由用双分号(::)隔开的命名空间(如包或类)的名字连接而成。
UserInterface::HelpFacility::HelpScreen
224.导航性(navigability)
说明是否可以穿过类的表达式中的二元关联得到与类的实例相关联的一个或几个对象。此概念不适用于n元关联(见文本)。导航性是枚举类型,值可以是true(可导航),false(不可导航)。
见导航效率(navigation effciency)。
语义
导航性说明角色名可否用于表达式,以穿过有此角色名的对象的关联,到达另一个关联端的对象。如果有导航性,关联定义了该角色名的另一个关联端的类的伪属性--即角色名可以向属性一样用于类的表达式,并得到值。角色名还用于表达约束。
没有导航性说明关联另一端的类"看不到"关联,因此不能用它构成表达式。没有导航性的关联不会创建源类到目标类之间的依赖关系,但是可能有其他子句创建这样的依赖关系。
没有导航性不是说没有穿过关联的方法。如果可能从其他方向穿过关联,可以在其他类的实例中进行搜索,找出指向对象的类,从而穿越关联。这种方法仅仅在小范围内适用。
n元关联不能定义导航性,因为这需要对类的集合一一定义导航性。这是可以实现的,但是作为一种基本属性就太复杂了。这不是说n元关联不能穿过,而是这样的规则过于复杂,难以用布尔值定义。
导航性通常与导航效率相关,但是UML规则中没有严格的要求。
表示法
导航关联表示为目标类上关联路径上的箭头。箭头说明穿越的方向(图13-131)。导航性的修饰属性可以省略(对于图中所有的关联)。箭头可以画在0个、1个或者两个关联端上。
为了方便,对于双向导航的关联可以将省略箭头。理论上,这可能会与两个方向都不能导航的关联混淆,但是实际上很少有这种关联,因此出现时可以特别表明。
没有必要标注"未确定"的导航性。如果没有确定导航性,也可以归入常见的状态。关于导航性的讨论只是对它作或者不作限制。
图13-131 导航性
225.可导航的(navigable)
一种可以用于表达式中穿越的关联或者连结。它的可导航属性为true。这种连结通常用一个或者几个箭头实现。
见导航性(navigability)、导航效率(navigation efficiency)。
226.导航(navigation)
在图中穿越连接,特别是对象模型中的二元链接和对象模型中的属性,从而得到对象的映射值。在后一种情况下,导航路径可以表示为属性名或者角色名的序列。
见导航性(navigability)。
227.导航效率(navigation effciency)
表明是否可能有效地穿越一个对象到另为一个或几个对象的二元关联。这个概念不适用于n元关联。导航效率与导航性相关,但不是它定义的属性。
见导航性(navigability)。
语义
可以用常规方法定义导航效率,以便符合抽象设计和各种程序设计语言的要求。如果得到关联的对象集合的花费正比于集合中对象的数目(不是集合的上界,那可能是无穷)加上某个常数相等,就认为可以有效地进行导航。计算复杂性时,花费是O(n)。如果多重性是1,或者0、1,访问的花费必须为常数,可以查变量长度列表得到。一种较松导航效率定义允许的最小花费为log(n)。
虽然通常用嵌入到包含对象属性的块中的指针来实现多重性为1的可导航关联,也可以用哈希表来达到外部实现,表中带有平均访问花费。这样,关联可以被实现为参与类之外的外部对象的查表操作。(某些实时情况下,应该规定最环情况下的花费,而不是平均花费。不必改变基本的定义,只要换上最坏情况下的花费,但是不能再使用哈希表等算法了)。
如果给定方向上不能进行导航,并不是说完全无法穿越,而是穿越的开销将是很大的--例如要在更大的表中查找。如果某个方向上的访问不经常出现,则查表是合理的选择。导航效率是设计概念,它允许设计者了解访问的开销。通常,导航隐含导航效率。
可能(如果很少)有在两个方向上都不能高效导航的关联。这种关联可能实现为连接的集合,在进行任何方向的导航时必须对该集合进行搜索。这是可以穿越的,但是效率很低。总之,这种关联的使用范围很小。
讨论
导航效率说明得到与给定对象相关的对象集合的效率。多重性为0..1或者1时,实现显然是源对象的指针。多重性为"许多"时,通常实现为包含许多指针的包含类。包含类自身可能驻留在类的对象的数据记录上。这由它是否可以通过开销常数(指针访问的常规情况)得到来决定。包含类必须是可以高效导航的。例如,所有关联的列表不是高效的,因为对象的连接和许多无用的连接混在了一起,需要查找。按照元素类元的列表是高效的,因为避免了不必要的查找。
在限定资格的关联中,从资格限定的元素出发设置导航性表示可以通过源元素和限定值高效地得到对象或者对象集合。这和用哈希表或按限定值(这是将资格限定作为模型概念的目的)索引二叉树查找的实现是一致的。
228.节点(node)
节点是运行时的物理对象,代表一个计算资源。通常至少有存储空间和执行能力。运行时对象和运行时构件实例可以驻留在节点上。
见位置(location)。
语义
节点包括计算设备和(至少商业模型中的)人力资源或者机械处理资源。节点可以用描述符或实例代表。节点定义了运行时可计算实例驻留的位置,可计算实例包括对象和构件实例。
物理节点有更多的特性,如能力、吞吐量、可靠性。UML没有预定义这些属性,但它们可以在UML模型中用构造类型或标签值建立。
用关联连接节点表示通信路径。这些关联可以有构造类型,以区分不同的通讯和通讯的不同实现。
节点是实现视图中的继承部分,不属于分析视图。配置模型中表示节点实例而不是节点类型。虽然节点类型有重要意义,但是各个节点的类型通常是匿名的。
节点是一种类元,可以有属性。通常,节点实例在部署图中表示。节点的描述符用处很小。
表示法
节点的表示看起来象立方体的偏方向投影。
节点描述符的语法是:
节点类型
其中节点类型是类元名字。
节点实例有名字和类型名字。节点带有下划线的名字表在节点中,或者节点下方。名字字符串的语法:
名字:节点类型
其中名字是各个节点的名字(如果有)。节点类型说明它是何种类型的节点。两个元素都是可选择的。
依赖箭头(箭头指向构件的虚线箭头)用于表示节点类型支持构件类型的能力。可以使用构造类型来声明依赖关系。
构件实例和对象可以表示在节点实例符号中。这说明该元素驻留在节点实例上。还可以用聚集和组成关联路径表示包含关系。
节点之间用关联符号相连。两个节点之间的关联说明它们之间的通讯路径。关联可以有构造类型,说明通讯路径的特性(例如信道或者网络的种类)。
举例
图13-123表示了包含一个对象(族)的两个节点,该对象从一个节点的构件向另一个节点移动。图13-132 节点之间的移动
229.注释(note)
表示备注或者其他文本信息的符号,例如方法体或者约束。
表示法
注释表示为右上角向下折的矩形。其中有不能有UML翻译的文本,或者文本的扩展(如嵌入文件)。注释可以为不同的模型元素提供信息,如备注、约束、方法等。注释通常不会明确说明其解说的元素的类型,但是可以从格式和使用中看出来。注释可以用虚线与元素相连。如果注释解释多个元素,虚线指向每个元素。
注释可以有关键字来说明其意义,如关键字《constraint》说明这是约束。
举例
图13-133表示了各种注释,包括操作的约束、类的约束和备注。
图13-132 节点之间的移动
图13-133 注释
130.对象(object)
封装了状态和行为的具有良好定义界面和身份的离散实体;即对象实例。
见类(class)、标识(identity)、实例(instance)。
语义
一个对象是类的实例,类描述了存在的可能对象集。一个对象可从两个相关视点来观察:作为一个实体,它在某个时刻有明确的值;作为一个身份持有者,不同时刻有不同的值。一个对象的快照有一个位置(在分布系统中),且每一个属性都有值。一个对象通过链集和其他对象相联系。
每一个对象拥有唯一的身份且可通过唯一的句柄引用,句柄可标识对象和提供对对象的访问。把对象作为一个身份是与合作实例相对应的,在合作实例中对象通过与其他对象交换消息在运行时进行联系。
在对象的完整描述中,每一个属性都有一个属性槽---即,每一个属性在它的直属类和每一个祖先类中都进行了声明。当对象的实例化和初始化完成后,每个槽都有了一个值,它是所声明属性类型的一个实例。当系统运行时,属性槽中的值可以改变,除非属性的可变性被隐藏。在操作执行的任何时刻,对象的值必须满足模型所施加的所有隐式和显式的限制。操作执行的过程中,限制可以暂时忽略。
如果执行环境允许多重类元,则一个对象可以是多个类的直接实例。在对象的直属类中和对象的任何祖先中声明的每一个属性在对象中都有一个属性槽。相同属性不可以多次出现,但如果两个直属类是同一祖先的子孙,则不论通过何种路径到达该属性,该祖先的每个属性只有一个备份被继承。
如果执行环境允许动态类元,则在执行期间对象可以改变它的直属类。如果可在过程中获得属性,则它们的值必须通过更改直属类操作指明。
如果执行环境允许多类元和动态类元,则在执行过程中可以获得和失去直属类。然而,直属类的数目不能少于一(类必须有结构,即使它是暂时的)。
可以调用对象去执行任何直属类的完整描述中的任何操作---即,对象拥有的直属和继承操作。
对象可以作为变量和参数的值,变量和参数的类型被声明为与对象相同的类或该对象直属类的一个祖先。换句话说,类的任何子孙的实例可以是变量的值,该变量的类型被声明为该类。这是替代原则。这个原则不仅有逻辑必要性,而且它的存在可简化编程语言的完整性。
表示法
对象是类的实例。实例符号的总原则是用相同的几何符号作为描述符,但用带有下划线的实例名将它作为个体区分开来。所有的值在实例中显示,但所有实例共享的特性在描述符中标注。
对象的规范符号包含两个分格的长方形。顶部包含对象的名和类,底部包含属性名和值的列表(图13-134)。
无需显示操作符,因为对于同一类的对象来说它们都是相同的。
顶部显示对象名和类名,都标以下划线,使用语法
对象名:类名
如果必要的话,类名可包括封装包的完全路径名。包名先于类名且用双冒号隔开。例如
displayWindow:WindowingSystem::GraphicWindows::Window
类的构造类型可以用文字描述(名字字符串上的书名号)或作为右上角的图标。对象的构造类型必须符合它的类的构造类型。
在显示多类对象的对象时,用逗号分隔类名列表。在一个合作中一些类可能起暂时作用。例如
aPersonrofessor,Skier
显示处于特定状态的对象,使用语法
对象名:类名[状态名列表]
列表必须是一个用逗号隔开可能同步出现的合法状态名列表。
显示类的变化(动态类元)时,对象必须显示两次,每个类一次。两符号通过一个"成为"关系连接起来,表明它们代表同一对象。
第二部分用列表显示对象的属性及值。每个值行的语法
属性名:类型=值
在类的属性声明中类型是多余的,可以省略。值用代表值的字符串指明。属性名不用下划线。
对象的名字可以忽略。在这种情况下,类名后的冒号应该保留。这表示一个匿名类对象,通过它的关系给予身份。每个包含一个匿名对象的符号表示一个独特的对象,它通过与其他对象之间的关系将自己区分开来。
对象类可以被省略(连冒号一起),但当可能避免混淆时应该显示。
属性值分格作为一个整体可以省略。
值没有意义的属性可以省略。
为了显示在计算过程中属性值的变化,用一个"成为"联系来表明这是同一对象的两个版本。
231.对象图(object diagram)
对象图显示某时刻对象和对象之间的关系。一个对象图可看成一个类图的特殊用例,实例和类可在其中显示。对象也和合作图相联系,合作图显示处于语境中的对象原型(类元角色)。
见图(diagram)。
表示法
对于对象图来说无需提供单独的形式。类图中就包含了对象,所以只有对象而无类的类图就是一个"对象图"。然而,"对象图"这条短语在刻画各方面特定使用时非常有用。
讨论
对象图显示对象集及其联系,代表了系统某时刻的状态。它包含带有值的对象,而非描述符,当然,在许多情况下对象可以是原型。用合作图可显示一个可多次实例化的对象及其联系的总体模型,合作图包含对象和链的描述符(类元角色和联系角色)。如果合作图实例化,则产生了对象图。
对象图不显示系统的演化过程。为此目的,可用带消息的合作图,或用顺序图表示一次交互。
232.对象流(object flow)
各种控制流表示了对象间的关系、对象和产生它(作输出)或使用它(作输入)的操作或转换间的关系。
见控制流(control flow)、对象流的状态(object flow state)。
语义
对象流是一类带有对象流状态的控制流,对象作为输入或输出。
表示法
用从源实体和目的实体的破折号来表示一个对象流。一个实体或两个实体可以是用对象符号表示的对象流状态。箭头上可用一个关键字来表明它是何种对象流(形成或复制)。如果箭头上没有标识,则成为联系。
见对象流状态(object flow state)、形成(become)、复制(copy)。
233.对象流状态(object flow state)
一个状态代表计算过程中某时刻某个类的一个对象的存在,诸如交互视图或活动图。
见控制流(control flow)、状态类(class-in-state)。
语义
无论活动图还是交互图都代表了在通过消息激发的目的对象操作中的控制流,但是消息并没有显示做为操作参量的对象流。这类信息流可用使用对象流状态的行为模型表示。
一个对象流状态代表计算过程中某时刻某个类的一个对象的存在,诸如交互图或活动图。对象可以是一个活动的输出和其他活动的输入。在活动图中,对象可以是一个转换的目的(通常用分叉表示,另外的分支是主控路径),以及一个活动的完成转换的源。当前一个转换激发,对象流状态变成活动的。这表示了类对象的创建。为了显示对象变为某个状态的过程,而非新对象的创建,一个对象流状态可声明为一个状态类。
一个对象流状态必须与它所表示的结果和参数的类型匹配。如果它是一个操作的输出,则必须与结果的类型匹配。如果它是一个操作的输入,则必须与参数的类型匹配。
如果对象流状态后跟着一个活动的完成转换,那么一旦对象值有效,活动便执行。无需附加的控制输入。换句话说,正确形式的数据建立是活动执行的触发器。
控制路径的前一个活动和值的对象流状态能导向一个复杂的转换,这表明一个活动的发生同时需要一个控制路径和值的出现。当所有的输入转换准备好后活动执行。多路径到达一个转换表示同步。
对象流状态通常对于人们理解输入输出关系很有用处,而不是为了让计算更简洁。用对象流状态表示的信息是已经可得的。
活动图中的活动产生事件可建模为一个对象流状态,它类属于信号。可使用〈〈信号〉〉构造类型。对象流状态是活动的输出。如果活动产生多个事件,对象流状态就是分叉的目标。
表示法
状态类的对象在活动图中显示,用一个长方形表示,包含带下划线的类名,后跟用中括号括住的状态名
类名[状态名]
例如
Order[Placed]
对象流状态的符号代表了对象做为过程中的一个状态存在,而不仅是简单的数据。对象流状态的符号(代表一个状态)可作为一转换箭头的目和多转换箭头的源。为了在活动图中把它们与普通转换区分开,它们用虚线而非实现表示。它们代表对象流。
举例
图13-135表示了活动图中的对象流状态。一个对象流状态由一个操作的完成创建。例如,Order[Placed]由Request Service 的完成创建。因为这个活动后跟着另一个活动,所以对象流状态Order[Placed]是分叉符号的一个输出。另一方面,状态Order[Entered]是活动Take Order完成后的结果,它没有其他后继活动。
图13-136显示了有关建房的活动图的一个部分。当框架建好后,木匠空闲下来可去建屋顶,房子可以装水管了。这些事件可以建模为信号对象流状态---Carpenter free 和 Frame ready。建屋顶和安装水管作为这些事件的结果。因此对象流状态作为活动的输入显示。在模型中,一个活动的完成产生一个事件,事件触发下一个活动,这些隐藏在活动的连接中。明显的事件要求可省略。因此,对象流状态信号的出现是为了提供信息,而非结构的执行。
讨论
对象流状态代表一个计算的数据流视图。然而,和传统的数据流不同的是,它只存在控制流模型中的有限部分(状态机或活动图),而不是处于数据流模型。这使它处于面向对象的框架结构中。面向对象将数据结构,控制流和数据流三个视点统一到同一个模型中。
234.对象生命线(object lifeline)
顺序图中的线代表对象的存在期。
235.对象集表达式(object set expression)
求值计算时产生对象集的表达式。
语义
发送动作的目标是一个对象集表达式。当这样一个表达式在运行时求值产生一个对象集,一个被标注的信号被平行发送到对象上。一个对象集可能产生一个元素,在这种情况下发送动作是一个普通的顺序对象。它甚至不产生元素(即空集),在这种情况下没有发送动作发生。
236.OCL
对象约束语言,一种指定约束和查询的语境有关语言。OCL不是用于编写 动作或可执行代码的。详细资料请看[Warmer-99]。
语义
对象约束语言(OCL)是一种语境有关语言,用于编写导航表达式、布尔表达式和其他查询语句。它可用于构建约束表达式,监护条件,动作,前置条件和后置条件,断言,和其他UML表达式。有关OCL完整的语法和语义描述请看
[Warmer-99].后面选择的概要包含了有关创建导航表达式和布尔表达式最有用的OCL语法。完整语言包括了大量的有关汇集和基类型的预定义操作符。
表示法
下面列出一些普通导航表达式的语法。这些形式可以链在一起。最左元素必须是对象或对象集表达式。可用的表达式意味着运行在一个值集上。详细资料和语法请看OCL描述。
项目.选择器
选择器是项目的一个属性名或项目链接的目标末端的角色名。结果是属性的值或相关的对象。结果是值或是值集依赖于项目的多样性和联系。
项目.选择器(参数列表)
选择器是项目的一个操作符名。结果是作用到项目上的操作返回值。
项目.选择器[限定值]
选择器指明了限定项目的限定关联。限定值是限定符属性的值。结果是通过限定符选择的相关对象。注意这种语法可以限定形式作为数组下标。
集合->集合特性
集合特性是内嵌的OCL集合函数名。结果是集合特性。如果集合特性不是预定义的OCL函数则不合法。下面列出了若干特性。
集合->select(布尔表达式)
布尔表达式写在集合中对象的项目中。结果是集合中满足布尔表达式的对象子集。
集合->size 集合中元素的数目。
self 表示当前对象(如果语境清晰则可省略)。
操作符 常用的数学和布尔操作符:= < > <= >= <> + - * / not
举例
flight.polit.training_hours>=flight.plane.minimum_hours
拥有足够训炼时间的飞行员集
company.employees->select(title="boss" and self.reports->size>10)
做过超过10次报告的老板的数目
237.操作(operation)
操作是可以调用对象执行的转换或查询的规格说明。它有一个名字和参数列表。方法是执行操作的过程。它有运算法则和过程描述。主动类的操作通过调用事件也可执行。
见 调用(call)、调用事件(call event)、方法(method)。
语义
操作指明了目标对象状态的转换(可能是从目标对象可达的系统其余对象的状态)或返回给操作调用者值的查询。操作可以方法或调用事件的形式执行,这导致主动对象的状态机的转变。操作由调用激发,调用者挂起直到操作执行完成,此后调用者继续调用点后的控制,同时如果操作使用了对象则接收返回值。
操作在类中声明。声明被其子孙类继承。如果另外的声明有相同的"匹配"签名,则为相同操作。执行时可指定一条关于匹配签名的规则来测试冲突,它包括操作名和参数类(而不是名字或路径),但不包括返回参数。相同的操作可出现在子孙类中。在该情况下,它被认为是继承声明的迭代而忽略。目的是利用名字匹配来允许一个操作在若干类中多次声明,从而形成不同的包。作为所有其他声明的共同的祖先的操作声明被称为起源。它代表了被其他操作继承的操作统治声明。
如果两个操作声明有相同的名字和相同的参数类型的有序列表(不包括返回参数),但其他特性不同(例如,一个参数在操作中是输入参数,而在别的操作中是输出参数),那么声明冲突,模型形式错误。
方法是一个操作的执行(也可以通过调用事件执行)。如果类中声明的操作无抽象特性,则类中就有一方法定义。否则,操作可能是抽象的(无方法),或是具体的继承方法。
结构
一个操作有以下组成要素。
并发 并发的语义是调用同一个被动实例、一个枚举值。可取值是
顺序 调用者必须协调以使每一时刻只有一个对对象的调用(对象的任何顺序操作)可执行。如果并发调用发生,则语义和系统的完整性不能保证。
监护 并发线程对一个对象(对象的任何监护操作)的多次调用可能同时发生,但同一时刻只允许一个调用发生。其他调用被阻塞直到第一个操作执行完成。确保不会由于同时发生的模块而产生死锁是建模者的责任。在同时发生的顺序操作的情况下监护操作必须正确执行(或阻塞自己),否则就不能声明监护语义。
并发 并发线程对一个对象(对象的并发操作)的多次调用可能同时发生。所有调用可按正确语义并发执行。并发操作设计时必须保证在同一对象的并发,顺序,或监护操作的情况下都能正确执行。否则,就不能声明并发语义。
多态 操作(方法或调用事件)的实现是否可以被后代类重载。如果可以,实现能够被后代类重载,提供方法的一个新定义或不同的状态机转换。实现呈现不同形式---即为多态。如果不可以,目前的实现不做任何改变的被后代继承。它只有一种形式。
查询 操作的执行是否改变系统的状态---即是否是一个查询。如果是,操作返回值,但无副作用。如果不是,它可能更改系统状态,但不能保证改变。
名称 操作的名称,字符串。特征匹配操作调用名称和参数类型列表(不包括参数名称或返回类型)。匹配的特征在类和它的祖先中必须是唯一。如果有迭代,则认为是操作的迭代声明,它必须完全匹配。如果匹配,则除了在最高层祖先的操作声明外,其他全被忽略。如果不匹配,则模型形式错误。
参数列表 操作参数声明列表。见 参数列表(parameter list)。
返回类型 调用的操作如果有返回值,则为返回值类型列表。如果没有返回值,则此特性为空值。注意许多语言不支持多返回值,但它仍是一个有效的建模概念,可通过许多方法实现,诸如把一个或多个参数作为输出值。
作用域 操作是否实施在对象个体或类本身(主作用域)上。可取值为:
实例 操作可以实施在对象个体上。
类 操作可以实施在类本身上---例如,创建类实例的操作。
说明 描述操作执行产生的效果的表达式---例如,前置后置条件。UML没有规定说明的格式,可采用各种格式。
可见性 对于其他类而非定义操作的类的操作的可见性。见 可见性(visibility)。
定义操作的方法有相同的组成元素。此外,它还有其他的组成元素
行为 描述方法实现的可选状态机。
体 描述方法过程的表达式。可用字符串或可能的分列格式来表示。尽管信息说明可用自然语言表示,体通常用编程语言表达。一般说来,如果使用状态机,就不使用体的值。
合作 合作集把方法的实现描述为角色(互操作)间的有序消息集。
调用事件的组成元素和操作相同。操作的实现必须指定一个或多个转换,转换可由调用事件触发。
表示法
操作用由操作的特性组成的字符串表示。缺省语法是
〈〈构造类型〉〉opt 可见性opt 名称(参数列表):返回类型opt{特性字符串}opt
构造类型,可见性,返回类型表达式,特性字符串(以及它们的定界符)可省略。参数列表可为空。图13-137显示了一些典型操作。
名称。操作(不保括参数)名称字符串。
参数列表。用逗号隔开的参数声明列表,由参数流向,名称和类型组成。整个列表包含在圆括号中(包括空表)。详见 参数列表和参数。
图 13-137。包含多种操作的操作列表
返回类型。用逗号隔开的类元(类,数据类型和界面)名称列表字符串。操作参数列表后跟一个冒号(:),冒号后跟类型串。如果不返回任何值(如C++ 的void),冒号和返回类型串可省略。一些但非全部编程语言支持多返回值。
可见性。可见性用符号'+','#',或'-'标识,它们分别表示公有public,保护protected,私有private。换种形式,可见性可用特性串中的关键字表示(例如,{visiblity=private})。这种格式在用户定义或依赖语言的选择时使用。
方法。操作和方法用相同的语法声明。处于泛化层次最顶端的操作特征是操作声明。后继类中的同等特征是操作的迭代声明。,当各个类分别发展时,这些特征对于声明方法或声明操作可能有用。如果操作声明具有抽象特性(操作名为斜体或用关键字abstract标注),声明就没有对应的方法。否则,声明用操作声明和实现方法表示。
利用操作名和有序的参数类型表,但不包括返回参数进行操作和方法匹配。如果剩余特性不一致(例如,输入参数与输出参数不匹配),则存在冲突,模型为非良性结构的。
如果两个相同的操作声明没有共同的祖先,然而却是从一个公共类继承来的,则模型为非良性结构的。在这种情况下,在继承了这两个操作的类中声明产生了冲突。
方法体。方法体可用缚在操作声明上的注释串表示。如果它是用某种语言(一种语义限制)写的正式的说明,说明的正文应该封装起来。否则,如果它只是行为的自然语言描述(注释),只需用正常的正文。方法声明和它的状态机或合作的联接没有明显表示,通常用编辑工具中的超级链接描绘。
说明。描述操作执行效果的表达式。这可用多种方法表达,包括正文,前置后置条件和不变量。无论用何种方法表达,应该根据操作对于系统状态可观察的效果来表述说明,而不是根据执行的运算规则。运算规则属于方法的范围。
说明用附在操作入口处的字符串表示。
查询。用按isQuery=true 或isQuery=false格式的特性串显示选择项。选择true也可用关键字query表示。缺省为选择false---即操作可改变系统状态(但并不保证改变)。
多态。用按isPolymorphic=true(重载) 或isPolymorphic=false(不重载)格式的特性串显示选择项。缺省为选择true---即可重载。
作用域。实例作用域操作用不带下划线的操作串指明。类作用域操作用不带下划线的名字串指明。
并发。用按concurrency=value格式的特性串显示选择项,value可取sequential,guarded或concurrency其中之一。
信号。关键字<<signal>>置于操作表中的某个操作前,这表示类接收信号。参数即是信号的参数。声明可以没有返回值。对象接收信号后的反应由状态机表示。在其他应用中,这个符号能表示类对象对于可建模为信号的错误条件和异常的反应,
表达可选项
参量表和返回值类型可省略(全部而非分别)。
可见性的表示可用不同的方法,诸如使用特殊图标或用组对元素类元。
操作特征串的语法可以是某个具体语言的语法,诸如C++或Smalltalk。特殊标识的特性包含在字符串中。
风格指南
● 操作名典型的以小写字母开始。
● 操作名以正常体显示。
● 抽象操作用斜体显示。
标准元素
语义。
238.定序(ordering)
用于表述集合是否是有序或无序的值集特性,诸如通过关联与一个对象相联系的对象集。
见关联(association)、关联端点(association)、多重性(multiplicity)。
语义
如果关联端点的多重性上界大于1,则在一个二元联系的另一端与一个对象向连的是一个对象集。定序特性就是声明集合是有序还是无序。如无序,则集合中对象无明显顺序,构成一个普通集合。如有序,集合中的元素有明显的顺序。元素的顺序是部分的关联表达的信息---即这是除元素自身信息外的附加信息。通过顺序可获得元素。当新链添加到关联中时,它在顺序中的位置必须由添加链的操作指明。位置可以是操作的一个参量或可能是隐含的。例如,某个操作将新链添加到已知链表的末尾,但新链的位置必须用某种方式指明。
注意有序集合不同于由元素的一个或多个特性序化的集合。一个顺序是由集合中的对象的值完全决定。因此,尽管可利用它完成功能,但不添加任何信息。换句话说,序化的关联信息是元素自身信息外的附加信息。
定序特性运用到任何有多重性元素上,诸如多重性大于1的属性。
定序关系可通过多种方式实现,但通常把实现作为指定语言的产生特性。实现的扩展
序化的集合需要对定序规则单独说明,最好把它作为限制。
表示法
定序用花括号里的关键词表示,关键词置于它所作用的路径末端(图13-138)。缺省关键词表示无序。关键词{ordered}表示它是一个有序集。为此目的,关键词{sorted}可用以表示一个通过内部值排序的集合。
对于多重性大于1的属性,定序关键词可放在属性串的后面,置于花括号内,作为特性串的一部分。
如果定序关键词忽略,集合无序。
图 13-138 有序和无序集
讨论
有序集合有关于顺序的信息,信息是附加在集合中实体本身上的。因此,它不可派生,而必须在实体添加进来时指明。换句话说,任何添加实体的操作必须指明实体在实体表中的位置。当然,将新实体插入到一个隐含位置的操作也能实现,诸如表头或表尾。然而仅因为一个集合有序,并不表示可允许实体的任何顺序。这些必须由建模者确定。一般来说,新实体在表中位置是新建操作的参数。
注意二元关系的定序必须对每一个方向单独指定。除非一个方向上的多重性大于1,否则定序无任何意义。一个关联可能完全无序,也可一个方向有序,另一方向无序,或两个方向都有序。
假定类A和类B存在一个关联,在B方向上有序。通常,对象A的操作添加一个新链,指明B对象和新链在已知B表上的位置。A对象的操作新建一个B对象,同时也新建一个A和B之间的新链。表被添加到由A维持的链表中。可能新建一始于B端的新链,但通常新链插入到A到B的表中,因为始于B端的表中的位置意义不大。当然,程序员可根据需要实现更复杂的情况。
两个方向都有序的关联不太常见,因为要指明两个方向上的插入点有些为难。但这也可能,特别是新链添加到每一方向上的确省位置时。
注意一有序集除实体集合信息外,不包含任何额外信息。类元在计算上节约时间,却不增加信息。它可认为是一种设计优化,无需包括在设计模型中。它可作为定序特性的一个值,但它无须为添加实体到集合的操作指定位置。通过检查需类元表中属性的方法自动决定新实体的位置。
239.正交子状态(orthogonal substate)
状态集中的一个复合状态可划分为子状态,所有子状态的活性是并行的。
见 复合状态(composite state)、并行子状态(concurrent substate)。
240.所有者作用域(owner scope)
表明特征是作用到单个对象上还是由整个类共享。
见 作用域(scope)、目标作用域(target scope)。
语义
所有者作用域表示对于每一个类的实例有一个不同的属性槽,还是整个类只有一个属性槽。对于操作,所有者作用域表示操作作用于一个实例,还是作用于类自身(例如新建操作)。有时简称为作用域。可取值为
instance 每一个类元实例有自己的单独的属性槽的拷贝。槽中的值独立于其他槽中的值。这是正常情况。
对于操作来说,操作作用在单个对象上。
class 类元自身有属性槽的一个拷贝。类元的所有实例共享此槽。如果语言允许类作为真实对象,则类的一个属性作为一个对象。
对于操作来说,操作作用到整个类上,诸如新建操作或返回整个实例集的统计数字的操作。
表示法
类级作用域的属性或操作带下划线(图13-139)。实例级作用域的属性或操
作不带下划线。
讨论
对于关联来说,链的源位置上是实例还是类元。但这条信息可由另一方向
上的目标作用域指明,所以所有者作用域没有必要,因此它不用于关联。
图 13-139 类级作用域的属性和操作
240.包(Package)
一个包(Package)元素对外的可见性可以通过在该元素的名字前面添加可见性标志来加以说明('+'表示公共,'-'表示私有,'#'表示被保护)。
可以画出包符号之间的关系以显示包中的一些元素之间的联系。特别的,包之间的依赖关系(不同于授权依赖关系,比如访问和导入)表明元素之间存在一种或多种的依赖关系。
表示可选项
工具可以通过选择性的显示某种可见性级别的元素,比如所有的公共元素,来说明可见性。
工具也可以通过图象标记,比如颜色或字体来说明可见性。
风格指导
人们希望内容庞大的包通过带有名称的图标来显示,而这些具体内容则可以通过"缩放成"一个更详实的视图来动态的访问。
图13-140。包和包之间的联系
示例
图13-140显示了一个订单处理子系统的包结构。这个子系统本身以一个带有原形的包来显示。它包含了几个普通的包。而包之间的依靠关系通过点划线来表示。这个图还显示了该子系统所依赖的几个外部包。这些也许是书架外的构件或图书馆元素。包之间的泛化表明了一个类包(Generic Package)的不同变化。比如,"外部存储"包可以被实现为"随机存储"或者"流存储"。
讨论
包被作为访问及配置控制机制,以便允许开发人员在互不防碍的情况下组织大的模型并实现它们。自然地,它们将成为开发人员希望的样子。更为特殊的是,要想能够起作用,包必须遵循一定的语意规则。因为它们是作为配置控制单元,所以它们应该包含那些可能发展到一起的元素。包也必须把必须一并编译的元素分组。如果对一个元素的改变会导致其他元素的重新编译,那这些元素也应该放到相同的包内。
每个模型元素必须包含在一个且仅一个包或别的模型元素里。否则的话,模型的维护、修改和配置控制就成为不可能。拥有模型元素的包控制它的定义。它可以在别的包里被引用和使用,但是对这个包的改变会要求访问授权并对拥有该包的包进行更新。
标准元素
访问,扩展,虚包(Facade),框架,桩(Stub),系统
242.参数(parameter)
参数即可以被改变,传递或返回的变量的声明。一个参数可能包括一个名字,类型和方向。参数被用于操作,信息,事件和模板。一个参数的使用方法把含有参数的操作或含有这种操作的类同这个参数的类联系起来。
参看: 变元(argument)、绑定(binding)
语义
当封装元素被使用时,参数就是与之联系的变元的存放地。它限定了该变元的可取值范围。它包括以下的部分。
缺省值 该参数没有变元对应时所使用的一个值表达式。在参数表接受变元时计算该 表达式。
方向 参数信息流的方向,是一个枚举值。取值如下:
In 一个传值的输入参数。对这个参数的改变对调用者不起作用。
Out 一个输出参数。它没有输入值。它的最终值对调用者是可用的。
Inout 一个可以修改的输入参数。该参数的最终值对调用者是可用的。
Return 一个调用的返回值。这个值对调用者是可用的。语义上来说,它同一个输出(out)参数没有区别,但是它的结果可以在一个内嵌的表达式里使用。
前面所列的选项并不是在所有的编程语言中都直接存在,但是各项所含的概念在大多数的语言中都有意义,而且可以被映射成一个有意义的表达式。
名字 参数名称。必须在所在的参数表内保证唯一。
类型 对一个类说明符(在大多数的过程中,是一个类,数据类型或者是接口)的引用。赋给该参数的变量必须是类说明符或其后代的一个实例。
表示法
每个参数都显示为一串文字,它可以分解为该参数的不同属性。缺省的语法如下:
方向 名字:类型=缺省值
方向。方向是操作名称前面的一个关键字。如果该关键字不存在,方向就是In. 方向的可选值为 in,out ,inout 和return。 返回参数通常显示在操作的别的地方,这时返回参数也不必标记为方向。
名字。名字被显示为一个符号串。
类型。类型被显示为一个符号串,该符号串是一个类,接口或者数据类型的名字。
缺省值。 该值被显示为一个表达式。该表达式的术语应为特定的工具所能理解,但并不显示为规范格式。
范围。如果这个范围是类,则操作符号串带有下划线;如果范围是实例,则操作符号串不带有下划线。
参数依赖关系。参数依赖关系表示成一个箭头,箭头方向是从含有该参数的操作或含有该操作的类到该参数的类。箭头上标注"参数"。
举举例:
Matrix ::transform(in diatance:Vector, in angle:real=0): return Matrix
以上所有的方向标号都可以省略。
243.参数表(parameter list)
对操作或模板所接受的值的说明。参数表是参数说明的一个有序序列。该序列可以为空,在这种情况下,操作不调用任何参数。
见参数(parameter)
表示法
参数表是参数声明的一个序列,由小括弧括起并由逗号分隔。
(参数表)
即使参数表为空,小括弧还是应该显示:
()
244.参数化元素(parameterized element)
参看 模板(template)
245.父亲(parent)
在泛化的联系中更具一般性的元素。对于类来说就称为父类。一个或多个父亲关系(即传递闭包)称为祖先。相反的称为子孙。
见 泛化(generalizateon)
246.参与(participates)
参与就是模型元素和联系或具体化的联系之间的连接。例如,一个关联中的类参与,一个合作中的类标志符角色参与。
247.被动对象(passive object)
自己本身不具备线程控制的对象。它的操作是在主动对象内的线程的控制下执行。
语义
主动对象是拥有控制线程的对象,它们可以激发控制行为。而被动对象是具有一个值但是不能激发控制的对象。但是当被动对象在处理由它自身内已经存在的线程所接受的请求时,对被动对象的操作可能会发送消息。
表示法
被动对象显示为一个类的矩形,其中的对象名字带有下划线。被动类显示为一个类矩形,其中的类名没有下划线。这些矩形具有正常的边界(没有加粗)。而主动对象在显示时则使用加粗的边界。
248.路径
联结各个标志的图形段之间的一个联结序列,通常被用来显示联系。
表示法
路径是图表中各个标志之间的图形化的联结。路径被用来说明各种各样的联系,比如,关联,泛化和依赖。两个联结在一起的段的结束端点是重合的。尽管有的工具只支持直线段和圆弧,段可以是直线段,圆弧或其他别的形状。(图130141)。理论上,线可以画成任意角度,尽管有的建模人员希望把线限制成直角,而且还可能为了虚包和摆放上更为容易,强制性的把线放到一个规则的网格内。通常来说,虽然路径的路线并不重要,但是,路径应该避免穿过封闭区域,因为穿过图形区域的边界可能具有语义上的含义。(比如,同一个合作内的两个类的关联应该画在合作区域内,表明这是同一个合作实例内的对象的关联;对应的,穿过某个区域的路径表明不同合作实例的对象之间的关联)。 更为精确的来讲,路径是一个拓扑结构。准确的路线并没有语义,但是与其他标号的联结和交叉有重要意义。准确的路径布局对可理解性和美观有很大影响,而且也会暗示出联系的重要性及其他的事情。但是,这种考虑是基于人而非基于计算机。人们希望工具能使路径的路由和重路由变的容易。
在大多数的图表中,线之间的交叉没有重要意义。为了避免交叉线的二义性,可以在交叉点上画一个小的半圆或者缺口(图13-142)。更为普遍的做法是,建模人员只是把一个交叉当作两条独立的线,避免同两个直角在它们的拐点处接触的情况发生混淆。
图13-142。 路径交叉
在一些联系中(比如 聚集和泛化),相同类型的几条路径可能联结到同一个标号上。如果不同模型元素的属性搭配,则这些联结到该标号的线段可以合并成一条线段,这样从该标号引出的路径就分支成为不同的路径而形成树。这完全是图形表示上的选择。概念上,单个路径都是有区别的。当不同段的建模信息不完全相同时,这种表示法可能就不会被使用图13-141。 路径
图13-143。有共享段的路径
249.路径名称(pathname)
包含元素的,嵌套的名称空间的名字联结而组成成的字符串。该字符串从包含整个系统的不明确且未命名的名称空间开始,以这个元素本身的名字结束。
语义
在一个系统内,路径名称唯一的表明了一个模型元素,例如属性或者状态。在表达式中它可以被用来引用一个元素。并不是每中元素都有名称。
表示法
路径名称被显示为一个嵌套的名称空间和元素名称的列表,之间由双冒号分隔。名称空间就是带有嵌套声明的包或元素。
Accounting:ersonnel::Employee::Address
属性 Address 存在于包 Employee 存在于包 Personel 存在于包 Accounting
路径名称就是对包中的有这个路径的前缀所命名的元素的引用。
249.模式(pattern)
模式就是一个参数化的合作。该合作代表参数化的类说明符,联系和行为的集合。通过把模型(通常是类)中的元素绑定到模式的角色上去,这些类说明符,联系和行为就可以应用到多种情况下。 所谓模式,就是合作的模板。
语义
模式代表的就是可以在一个或多个系统中多次使用的一个参数化的合作。要成为一个模式,一个合作必须能够在多种情况下都能够应用,以便可以给它命名。在多种情况下都能工作是个待解决的问题,而模式就是对该问题的一个解答。当然,模式并不是该问题的唯一解答,但它是已经被证明非常有效的方案。大多数的模式都有缺点和优点,这主要取决于更为广阔的系统的各个方面。建模人员在决定使用某种模式之前应该充分考虑这些优点和缺点。
一个UML参数化的合作代表了某种类型模式的结构和行为方面的视图。模式也包括不被UML直接修改的别的那些方面,比如缺点和优点的列表。在这些方面中,许多可以用语言表达。参看[Gamma -95]可以获得对模式的全方位的理解,并且可以看到一些设计模式的目录。
根据模式产生合作。合作可以用来说明设计结构的实现。通过参数化它的各个要素,相同类型的合作可以应用多次。模式就是参数化的合作。通过绑定值,通常是类,到它的参数上去,模式就被实例化为合作。通常来讲,对于参数化的角色,通过为每-个角色声明一个类就可以确定一个模板。典型的来讲,模式中的关联角色是不被参数化。当模板被确定后,它们就代表了绑定到该合作上的类之间的关联-也就是说,为生成合作而绑定模板会产生额外的关联。
表示法
为了生成合作而绑定模式被显示为虚线椭圆,椭圆中包含了模式的名字(图13-144)。从绑定标号的模式到每个参与合作的类(或者 别的模型元素)之间划一条虚线。每一条线都标注有参数的名字。在大多数的情况下,合作中角色的名字就可以被用作参数的名字。所以,绑定标号的模式可以表示出设计模式的应用,同时也可以显示出模式使用过程中出现的实际 的类。模式绑定通常并不能把由该绑定产生出的合作的内部结构表示出来。这一点由绑定标号暗示出来。
|