138.激发(fire)
激发一个转换。
见运行至完成(run to ,ompletion)、触发(trigger)。
语义
当转换要求的事件发生时,如果满足监护条件,转换将执行其活动,活动状态改变。
对象接收到事件后,如果状态机处于运行至完成这一步骤,则保存该事件。步骤完成后由状态机处理这一事件。如果当前对象所处的状态含有转换,则相应转换被触发。如果是有多个源状态的复杂转换,则转换进行前所有源状态必须是活动的。源状态活动完成后,可以执行完成转换。如果源状态为组成状态,所有直接子状态完成或者达到终态后可以执行完成转换。
处理事件后,计算监护条件(如果有的话)。如果条件的布尔表达式为真,转换将激发。激发转换上的活动,转换的目标状态成为活动的(内部转换不改变状态)。在状态变化中,执行对象的原始状态和转换的目标状态最短路径上的任何出口活动和入口活动。注意,原始状态可能是转换源状态的嵌套子状态。
如果转换不满足监护条件,则不会激发。可能激发其他监护条件满足的转换。
如果有多个转换可以激发,其中只有一个能真正激发。嵌套状态内的转换比外部转换优先。否则转换的选择是不定的,这符合现实世界中的常见情况。
实际上,实现可以确定转换激发的顺序。这并不改变语义。合理设置监护条件以保证彼此互斥,可以达到相同的效果。更简单的方法是采用"如果没有进行其他转换,则使用本转换"。
延迟事件(Deferred events)
如果某个事件或其祖先在某个状态中被定为延迟的,则它将不触发转换,直到对象进入一个不要求当前事件延迟的状态位置。对象进入新的状态后,原来延迟而现在不延迟的事件成为"pending (有待解决的)",并以不确定的顺序出现。如果第一个待解决事件没有触发转换,则它将被忽略,下一个待解决事件出现。如果事件发生引起了状态的转换,则根据新状态的延迟情况,重新确定尚处于待解决的延迟事件,建立新的待解决事件集。
实现可以更严格地规定延迟事件的处理顺序,或者用某种操作来限制顺序。
139.流(flow)
在不同连续时间点上同一个对象两个版本之间的关系。
见成为(become)、复制(copy)。
语义
流关系联系了同一对象在不同连续时间点的两个版本。它可以连结实例级交互中一个对象的两个值,或者描述符级交互中同一对象的两个类元角色。它代表对象从一个状态到另一个状态的转换,可以代表值、控制状态、位置改变。
流依赖关系的构造类型有成为(become)和复制(copy),用户可以增加其他构造类型。
表示法
流关系用带有构造类型的虚线箭头表示,构造类型不能省略。
标准元素
成为、复制
140.控制焦点(focus of control)
顺序图中的一个符号,表示对象直接或者间接(通过子程序)执行一个活动的一段时间。
见激活(activation)。
141.字体使用(font usuage)
用不同字体或者其他图形标志来区分正文。
见图形标志(graphic marker)。
讨论
斜体字表示抽象类、属性、操作。其他字体用于强调或者区别表示语法中的不同部分。建议对于类元名字、关系名字用黑体字;对于内容,属性、操作、角色名等用正常字体。分格的名字用特殊字体,选择权在于编辑工具。工具可以选择字体来强调元素、区分保留字、表示元素的特定属性。也可以允许用户选择字体。对于颜色有类似的考虑,有色盲的人可以不用颜色区分。上述所有内容是对于本书所述表示法的扩展。
142.分叉(fork)
复杂转换中,一个源状态可以转入多个目标状态,使活动状态的数目增加。
反义词:结合。
见复杂转换(complex transition)、复合状态(composite state)、结合(join)。
语义
分叉是指有一个源状态和多个目标状态的转换。如果在源状态活动时出现触发事件,所有目标状态将成为活动的。目标状态必须是并行组成状态中的不同区域。
表示法
分叉表示为有一个转入箭头和多个转出箭头的粗线,它可以带有转换标签(监护条件、触发事件和活动)。图13-101是进入并行组成状态的明显分叉。
图13-101 分叉
143.形式参数(formal argument)
见参数(parameter)
144.框架(framework)
为某个域中的应用程序提供可扩展模板的泛化结构。
见包(package)。
145.友元
一种使用依赖关系,允许用户访问服务提供者。
见访问(acess)、导入(import)、可视性(visibility)
语义
友元依赖关系用于保证一个操作或者一个类对使用类的内容的许可,虽然从另外角度看来许可不够充分。它通常是规则中的异常,这种功能要小心使用。
表示法
从得到许可的类或者操作向提供内容的类引一条虚线表示友元依赖关系;构造类型关键字《friend》标在箭头上。
146.完整描述符(full descreptor)
一个直接实例的完整隐含描述。一个完整描述符通过继承其所有祖先组装而成。
见直接类、继承、多类元。
语义
实际上,对于类或者其他元素的声明只是其实例的部分描述,称为类片断(class segment)。通常类的对象含有比它的直接类所描述的更多的结构。对实例所有的属性、操作和关联的描述称为完整描述符,它通常不由模型或程序表示。继承规则的目的就是提供一种自动将类片断组成为完整描述符的方法。理论上有不同的实现方式,称为元对象协定(metaobject protocol)。UML为继承定义的一系列规则,涵盖了大多数程序设计语言,也可用于建立概念模型。注意,可能存在其他可能性,如CLOS语言等。
147.功能视图(functional view)
这种视图将系统分解为功能或者提供功能的操作。通常认为功能视图不是面向对象的,可能导致不易维护的结构。传统开发方法中,数据流图是功能视图的核心。UML不直接支持这种视图,但是活动图中有一些功能特性。
148.可泛化元素(generalizable element)
可以参与泛化关系的模型元素。
见 泛化(generalization)、继承(inheritance)
语义
可泛化元素可以有父和子。被类元成带有元素的变量可以带有该元素后代的实例。
可泛化元素包括类、用例、其他类元、关联、状态和合作,它们继承其祖先的特征。每种可泛化元素的哪个部分是继承来的,要看元素的种类。例如类继承属性、方法、操作、关联中的地位和约束;关联继承参与类(本身可被特化)和关联端的特性;用例继承属性、操作、与参与者的关联、与其他用例的扩展和包含关系、行为序列。状态继承转换。
见泛化(generalization)、关联泛化(association generalization)、用例泛化(use case generalization)。
结构
可泛化元素的属性声明它可以在泛化关系中的何处出现。
抽象 说明可泛化元素是描述直接实例的,还是抽象元素的。True表示元素是抽象的(不能有直接实例);false表示它是是体(可以由直接实例)。抽象元素的实体后代才能使用。带有无方法操作的类是抽象的。
叶 说明可泛化元素是否可以特化。True表示元素不能有后代(叶);false表是可以有后代(无论当前是否有后代)。作为叶的抽象类只能起组织全局属性和操作的作用。
根 说明元素是否必须为无祖先的根。True表示元素必须为根;false表是不必为根,可以有祖先(无论当前是否有祖先)。
注意:声明叶或者根不影响语义,但这种声明可以给设计者提示。如果能避免对全局变量的分析或者对多态操作的全局保护,就可以有更高的编译效率。
标准元素
叶
149.泛化(generalization)
一个较广泛化的元素和一个较特殊的元素之间的类元关系。特殊化的元素完整的包含了广泛化的元素,并含有更多信息。特殊化的元素的实例可以用于任何使用广泛化元素的地方。
见泛化关联(association generalization)、继承(inheritance)、可替换规则(substitutability principle)、用例泛化(case generalization)。
语义
泛化是两个同类的可泛化元素之间的直接关系。其中一个元素被称为父,另一个为子。对类而言,父称为超类(superclass),子成为子类。父所说明的直接实例带有所有子的共同特点,子所说明的实例是上述实例的子集,不仅有父的特征,还有独有的特征。
泛化是一种反对称关系。按照一个方向转变成为父,另一个方向引向子。在父方向上经过一个或几个泛化关系的元素称为祖先;在子方向上经过一个或几个泛化关系的元素称为子。不允许出现泛化环,一个类不能既是自己的祖先又是自己的后代。
在最简单的情况下,类(或者其他可泛化元素)有单一的父。在复杂情况下,子有多个父。子继承了父的所有结构、行为和约束,称为多重继承(或者多重泛化)。父元素对子元素有可视性。
关联、类元、状态、事件和合作都可以泛化。
关于关联的泛化的应用,见关联泛化。
关于用例的泛化的应用,见用例泛化。
节点和构件类似于类,它们的泛化与类类似。
约束
约束可以应用于一列泛化关系,以及有同一个父的子。可以规定下列属性:
互斥 一个祖先不能有两个子(多重继承时),实例不能同时成为两个子的间接实例(多重类元语义)
重叠 一个祖先可以有两个或者更多的子,实例可以属于两个或者更多的子。
完整 列出了所有可能的子,不能再增加。
不完整 没有列出所有可能的子,有些已知子没有声明,还可以增加新的子。
表示法
类元之间的泛化关系表示为子元素(如子类)到父元素之间的实线路经,路径指向更广泛的元素的一端带有空心的三角形(图13-102)。指向父的线可以是组成或者树(图13-102)。图13-102 泛化关系图13-103 树形泛化关系
泛化还可以应用于关联,但是太多的线条可能使图很乱。为了标明泛化箭头,可以将关联表示为关联类。
如果图中没有标出模型中存在的类,应该在相应位置上用省略号(...)代替。(这不表示将来要加入新的类,而是说明当前已经有类存在。这种方发表示忽略的信息,而不是语义元素)。一个类的子类表示为省略号说明当前至少有一个子类没有在视图中标处。省略号可以有描述符。这种表示法是由编辑工具自动维护的,不用手工输入。
表示选项
到一个超类的一组泛化路径可以被表示为有一段公用路经(包括三角形)的树,树枝指向子类。这只是一种表示法,不代表n维关系。在当前模型中,每对超类--子类之间有一个泛化关系。弧分开来画没有语义上的区别。
如果在几个子类公用的泛化三角形上带有文本标签,则标签适用于所有路径。换言之,是所有子类共享的属性。
举例
图13-104是泛化关系上声明的约束。图中表示了"树形"泛化(路径为平行线,有公用的箭头);同时表示了"二元形"泛化(每一对父--子关系有独立的箭头)。图13-104 泛化约束
定义泛化关系中的元素时不用了解这一元素,但是子元素必须知道父元素的结构。通常,父元素就是为了供子元素扩展而设计的,因此设计时应了解预期的子元素。泛化关系的优点之一就在于经常可以出现设计父元素时没有想到的子元素,这带来了更强的功能。
实现关系与泛化关系类似,不过仅仅继承了行为说明。如果说明的元素没有属性、关联,而只有抽象操作,则泛化和实现是相同的。实现关系不生成用户,因此操作必须在用户中,或者从其他元素处继承来。
标准元素
完整,互斥,实现,不完整,重叠
150.图形标记(graphic marker)
一种标记元素,如几何图形、纹理、填充模式、字体、颜色等。
见字体使用(font usage)
表示法
表示符号是由不同的图形标记构成的。一个图形标记本身没有语义作用,但是表示法的目的就是尽可能多地组成使用图形标记。
有些图形标记用于构造预定义的UML符号,而其他不用于标准表示。颜色没有被赋予含义,因为有些打印机不支持彩色,有些人不能分辨色彩。这些未定义的图形标记可以按照建模者或者工具的需求供编辑工具使用。
UML表示法只允许有限的图形扩展。图标或图形标记(如纹理、颜色)可以与构造类型联系起来。UML没有定义图形说明的格式,但是有很多位图和格式可供图形编辑器使用(虽然其可移植性很难满足)。
图标说明及其替代表示的一般形式易于理解,我们也允许工具开发者溶入自己的想象--注意,扩展性的过度使用可能会造成工具可移植性的减弱。
151.监护条件(guard condition)
进行相关转换之前必须满足的一个条件。
见分支(branch)、条件线程(conditional thread)、结合状态(junction state)、转换(transition)
语义
监护条件是一个布尔表达式,它是转换说明的一部分。收到转换的触发事件之后,系统保存该事件直到状态机已经完成任何运行至完成步骤,随后进行事件处理,计算监护条件。如果条件为真,则可以进行转换(如果有多个转换可以进行,只能进行一个)。事件处理时进行测试。如果此时条件为假,除非触发事件再次出现,否则不再重新计算监护条件。
监护条件必须是一个询问--它不能修改系统的值或者状态的值,又不能有副作用。
完成转换也可以有监护条件,此时,它选择一个分支执行。
表示法
监护条件是转换字符串的一部分,它是用方括号括住的布尔表达式
[布尔表达式]
表达式中用到的名字必须是转换内部可见的,可以是触发事件的参数或者当前对象的属性。
152.书名号(guillemets)
(《》)在法语,意大利语和西班牙语中表示引用。在UML表示表示法中表示关键字和构造类型。许多字体中都有,必要时可以用两个尖括号代替。(<< >>)。
见字体使用。
153.历史状态(history state)
一种伪状态,说明当前的内部组成状态记得它存在之后曾经有的活动子状态。
见组成状态、伪状态、状态机、转换
语义
历史状态允许顺序组成状态记住从组成状态发出的转换之前组成状态的最后一个活动子状态。转向历史状态的一个转换将使前一个活动子状态再次成为活动的,并执行相应的入口活动和出口活动。历史状态可以有来自外部状态或者初始状态的转换。可以有一个没有标签的向外转换,该转换表示原先保存的历史状态。当没有保存的状态时,转向历史状态就会转向它。历史状态不能有来自组成状态内部的其他转换。
历史状态可以记忆浅历史和深历史。浅历史状态保存并激活与历史状态在同一个嵌套层次上的状态。如果一个转换从嵌套子状态直接退出组成状态,将激活组成状态中顶级的终止子状态。深历史状态记忆组成状态中更深的嵌套层次的状态。要记忆深状态,转换必须直接从深状态中转出。如果一个转换是从深状态转换到一个浅状态,并由此转出组成状态,将被记忆的将是浅状态的转换。到一个新历史状态的转换恢复任何层次上曾激活的状态。在这个过程中,如果入口活动出现在包含所记住状态的内层状态上,则执行该入口活动。组成状态可能同时有深浅两种历史状态,进入的转换必须连到二者之一。
如果组成状态进入终态,则它将丢弃所有保存的历史状态,好像从没进入过此状态一样。
表示法
浅历史状态用带有H的小圆圈表示,如图13-105所示。深历史状态是带有H*的圆圈。图13-105 历史状态
154.超级链接(hyperlink)
两个表示元素之间可以通过某些命令穿越的不可见连接。
见图(diagram)。
表示法
纸面上的表示法不包含隐藏信息。但是计算机屏幕上的表示法可以带有附加的不可见的超级链接,它们在静态图中不出现,但是在动态图上可以被激活,从而访问其他信息。这些信息或者在图形视图中或者在文字表中。这种动态链接如同可视信息一样,是动态表示法的一部分。本文没有限制它们的使用,只是我们没把它们当成工具的必要功能。本文试图为UML定义一种静态表示法,但是有些有用信息难以在这些视图中表示。另一方面,我们对动态工具的了解不够,又不想对创新的动态表示法只字不提。最终,成熟的动态表示法将成为标准,但是目前为时尚早。
155.标识(identity)
一个对象的继承属性,用于将它区别于其他对象。
见数据值(data value)、对象(object)。
语义
对象彼此是不同的。一个对象的标识符是它的概念句柄,是一个供其他对象引用或确定的继承特征。概念上,对象不需要用主键(key)或其他机制来标定自身,这种机制不应该存在于模型中。在实现中,标识符由地址或者主键实现,但它们是基本实现结构的一部分,不用显示地列为大多数模型的属性。
156.非良性结构(ill formed)
模型的结构设计不正确,其中有一个或多个预定义的规则或约束被违反。对比:结构良好。
见冲突(conflict)、限制(constraint)。
语义
违反良好结构规则和约束的模型是不能使用的,因为其语义是矛盾的。使用这种模型将产生无意义的结果。建模工具有责任找出非良性结构并加以隐藏,防止出现更大的问题。因为有时会使用UML内置语义之外的扩展结构,所以并不总能保证自动识别。此外,自动检查不能保证操作的一致性。因此,在实践中应该结合自动识别与人工识别。
完成的模型必须是结构良好的,但是模型建造的某个中间步骤生成的模型版本可能是非良性结构的,因为那只是未完成的框架。将一个可用的模型修改为新的模型的过程中,也可能生成非良性结构的模型。这类似于编写程序--供编译的程序必须是可用的,但是文本编辑区的中间版本可以是不能用的。因此,支持工具必须可以编辑和保存非良性结构的模型。
157.实现(implementation)
1. 定义某事物是如何构造、计算的。例如,类是类型的实现;方法是操作的实现。对比:说明。实现和说明之间是实现关系。
见关系(realization)
2. 用可执行的媒介(如程序设计语言、数据库、数字化硬件)描述系统功能的一个步骤。对实现而言,必须产生下层的决策以使设计适合具体的实现媒介,并与环境相适应(每种语言有各自的限制)。如果设计得好,实现的决策将是局域性的,任何决策不会影响系统的全局。这一步由实现层模型捕捉,特别是静态图和代码。对比:分析、设计、实现和配置。
见开发过程(development process)、建模步骤(stages of modeling)。
158.实现类(implementation class)
物理实现的类的构造类型,包括属性、与其他类的关联和操作的方法。一个实现类将用于具有静态单类元的传统面向对象语言。这样,系统中的一个对象必须有且只有一个实现类作为它的直接类。与类型不同,类的构造类型允许多个类元。在某些语言中(如JAVA),对象可以有一个实现类和多个类型,实现类要与类型一致。
见类型(type),其中对比了类型和实现类。
159.实现继承(implementation inheritance)
继承父元素实现--继承结构(如属性和操作)与代码(如方法)。相反接口继承包括了对接口说明的继承(操作),但是不继承方法和数据(属性和关联)。
UML中泛化的意义包括接口和实现的继承。如果仅仅继承实现(私有继承),可以在泛化关系上使用关键字《implementation》。如果只要继承接口,可以使用到接口的实现关系。
见泛化(generalization)、继承(inheritance)、接口继承(interface inheritance)、私有继承(private inheritance)。
160.实现视图(implementation view)
模型的一种视图,包含系统中构件的静态声明、依赖关系和可能由构件实现的类。
见构件图(component diagram)。
161.导入(import)
许可依赖关系的一种构造类型,其中提供者包中的元素名字被加入用户包的命名空间。
见访问(acess)、包(package)、可视性(visibility)。
语义
提供者包的命名空间中的名字被加入用户包的命名空间,访问指定的可视性规则不变。如果导入的名字和原有命名空间的名字冲突,说明出现模型为非良性结构。
见访问(acess),以及访问和导入的可视性规则。
表示法
用虚线箭头从得到访问权限的包指向提供者所在的包,箭头上带有构造类型《import》。
162.不活动(inactive)
不活动的状态,不能由任何对象处理。
163.初始(inception)
软件开发过程的第一步,这期间设计计算系统的原始方案,开发某些分析视图和少量其他视图。
见开发过程(development process)。
164.包含(include)
基用例与包含用例之间的关系。说明如何将包含用例中定义的行为插入基用例定义的行为中。基用例可以看到包含用例,并依赖于包含用例的执行结果。但是二者不能访问对方的属性。
见扩展(extend)、用例(use case)、用例泛化(use case generalization)
语义
包含关系联系了基用例和包含用例。关系中的包含用例不是能够独立实现的类元,而是显式说明插入执行基用例的用例实例中的附加行为序列。一个基用例可以有多重包含关系。同一个包含用例可以被包含于多个基用例中,这些基用例之间不必有任何关系。只要每个插入在基用例的不同位置,同一对基用例和包含用例之间可以有多个包含关系。
包含用例可以访问基用例的属性或者操作。包含用例提供了可被多个基用例重用的特有行为。基用例可以看到为它设置属性值的包含用例,但不能访问包含用例的属性,因为当前基用例重新得到控制后,包含用例已经结束了。
注意:(所有种)附加内容可以嵌套。一个包含可以是各种进一步包含、扩展或泛化关系的基。
结构
包含关系有下列属性:
位置 基用例的行为序列体中的位置,在此位置处可以插入包含。当执行基用例实例达到该位置时,用例实例执行包含用例,随后继续执行基用例。包含是基用例行为序列中的显式语句,因此,位置是隐含的。这与扩展关系不同。
包含只执行一次,通过引用包含的基用例行为序列中的循环可以达到多次包含的效果。
表示法
虚线箭头从基用例指向包含用例。箭头上带有关键字《include》(图13-106)。位置可以作为属性标在箭头边上,但通常作为基用例的文本部分引用,在图中不表示。图13-107是基用例行为序列。
图13-107 用例的行为序列
165.增量式开发(incremental development)
系统模型和其他产物的开发形成一系列的版本,每个版本完成一定程度上的功能和细化,每个版本都比上一个增加了细节内容。这种方法的优点在于每个新的版本对上一个版本进行少量改动,不易出错。这种方式与迭代开发概念密切相关。
见开发过程(development process)。
166.间接继承(indirect instance)
一个实体,该实体是一个元素(如类)的实例,同时又是该元素子的实例。就是说它是一个实例,但又不是直接实例。
167.继承(inheritance)
通过这种机制使得一个更具体的元素遵从一个更广泛的元素定义的结构和行为。
见完整描述符(full descriotor)、泛化(generalization)。
语义
继承使得可泛化元素的完整描述符能自动通过组装泛化层次的声明段构造出来。泛化继承是一棵模型元素(如类)的声明构成的树(实际上是偏序树)。但每个声明都不是针对完整可用的元素的,每个声明只说明该元素比它的祖先增加的内容,继承就是将这些递增的声明组成为说明实例的完整说明的(隐含)过程,这些完整说明描述实际的实例。
可以认为每个可泛化元素都有两个描述符:一个片段描述符和一个完整描述符。片段描述符是模型中元素所声明的递增特征表--例如类声明的属性和操作。元素和其父的片段描述符是不同的,模型中不会明确地出现完整描述符。它是元素实例的完整描述--例如类的对象的所有属性和操作。完整描述符是元素和其父的片段描述符的联合体。
继承就是对元素的递增定义,其他细节如查找算法等等只是特定语言的实现机构,而不是核心定义的一部分。虽然这种解释看来有点奇怪,但它不需要多数其他定义中的实现过程,同时又与这些定义兼容。
冲突
如果继承的片段集合中多次出现同一特征,就可能会出现冲突。继承集中的属性只能声明一遍。如果多次声明就会导致冲突,说明模型为非良性结构。(这一限制不是基于逻辑推理,而是为了防止出现必须用路径名区分属性时可能产生的异义)
操作可以被多次声明,只要声明相同(方法可以不同),或者子声明强化了某个继承声明(如将子声明为队列或增加它的并行状态数)。子声明的方法取代(重载)祖先的方法声明,不会有冲突。如果从没有祖先关系的两个元素中继承到了不同的方法,则会出现冲突,说明模型为非良性结构。
讨论
泛化是元素之间的类元关系,它解释了一个元素是什么;继承是连接共享递增声明,从而形成元素的完整声明的机构,这两者是不同的,但有着密切的关系。在泛化关系上应用继承机构,可以实现说明的分解和共享,以及多态行为。这是UML和多数面向对象语言使用的方式,但是某种程序设计语言还可能采用其他方法。
168.初始状态(initial state)
转换的目标状态是组成状态的边界时,用来指明其默认起始位置的伪状态。
见复合状态(composite state)、创建(creation)、入口动作(entry action)、 初始化(initialization)、结合状态(junction state)
语义
为了实现封装,应该尽可能地将组成状态的外部视图与内部细节分开。从外部看,组成状态是隐藏了内部结构的不透明实体,从外部视图看,转换的起止点都是状态自身。从内部视图看,它们连到状态内的子状态。
初始状态是一个伪状态,它代表了进入转换与组成状态边界的结合点。它不是真实的状态,不能保留控制权,它只是说明控制应该转向哪里的语法表达式。初始状态必须要有一个出去的无触发转换(没有事件触发器的转换,因此遇到初始状态可自动有效)。完成转换连接到组成状态中的一个真实状态上。完成转换上可以有动作,该动作在状态的入口动作(如果有)之后遇到状态时执行。除了入口活动(在所有入口处执行,否则缺省)之外,它还允许动作与缺省入口关联。这个活动可以访问隐含的当前事件--即由最终使得转换转向初始状态的转换中的第一片段触发的事件。
初始状态不能有带触发事件的向外转换,进入转换与进入其组成状态的转换是一样的,也应该避免,应该将这种转换与组成状态相连。
通常初始状态上的转换是无监护条件的,因而必须是来自初始状态的唯一转换。多个向外的转换将带有监护条件,这些条件必须涵盖所有的可能性(或者把某个条件设为"其他")。关键是控制权必须马上离开初始状态。它不是真实的状态,必须激活某个转换。
类的顶级状态中的初始状态,代表了类的新的实例的创建。当执行它的向外转换时,隐含的当前事件是创建对象的事件,它具有由构造操作传来的变元值。这些值可供向外转换上的活动使用。
对象创建
一个类的大多数组成状态的初始状态都很类似,它可能带着标有关键字《create》的触发事件,以及带参数的有名字的触发事件。可以有多个此类转换具有不同触发事件。当生成类的对象实例时,触发与其创建操作相应的转换,该转换从调用创建操作处得到变元值。
表示法
组成状态中的初始状态表示为小的实心圆,其上可以有向外转换箭头。一个组成状态中只能有一个初始状态(直接)。但是嵌套的组成状态中可以有多个组成状态。
举例
图13-108中,我们从状态X开始,出现事件e之后,激活转换并执行活动a,转换指向状态Y,执行入口活动b之后,初始状态成为活动状态。随后立即进行外向转换,执行活动c并进入状态Z。
如果系统处于状态X时发生事件f,则激活另一个转换执行活动d,转换直接到达状态Z,这一过程中不包括初始状态,因为控制权转交给Y,所以要执行活动b,但不执行活动c。
图13-109中的初始状态带有分支。假设系统开始于X状态,当事件e出现时,执行活动a,系统则进入状态Y并完成入口活动b,控制权转给初始状态,测试当前对象的size属性;如果值为0,控制转入状态Z;如果值不为0,控制转入状态W。
图13-107 用例的行为序列
165.增量式开发(incremental development)
系统模型和其他产物的开发形成一系列的版本,每个版本完成一定程度上的功能和细化,每个版本都比上一个增加了细节内容。这种方法的优点在于每个新的版本对上一个版本进行少量改动,不易出错。这种方式与迭代开发概念密切相关。
见开发过程(development process)。
166.间接继承(indirect instance)
一个实体,该实体是一个元素(如类)的实例,同时又是该元素子的实例。就是说它是一个实例,但又不是直接实例。
167.继承(inheritance)
通过这种机制使得一个更具体的元素遵从一个更广泛的元素定义的结构和行为。
见完整描述符(full descriotor)、泛化(generalization)。
语义
继承使得可泛化元素的完整描述符能自动通过组装泛化层次的声明段构造出来。泛化继承是一棵模型元素(如类)的声明构成的树(实际上是偏序树)。但每个声明都不是针对完整可用的元素的,每个声明只说明该元素比它的祖先增加的内容,继承就是将这些递增的声明组成为说明实例的完整说明的(隐含)过程,这些完整说明描述实际的实例。
可以认为每个可泛化元素都有两个描述符:一个片段描述符和一个完整描述符。片段描述符是模型中元素所声明的递增特征表--例如类声明的属性和操作。元素和其父的片段描述符是不同的,模型中不会明确地出现完整描述符。它是元素实例的完整描述--例如类的对象的所有属性和操作。完整描述符是元素和其父的片段描述符的联合体。
继承就是对元素的递增定义,其他细节如查找算法等等只是特定语言的实现机构,而不是核心定义的一部分。虽然这种解释看来有点奇怪,但它不需要多数其他定义中的实现过程,同时又与这些定义兼容。
冲突
如果继承的片段集合中多次出现同一特征,就可能会出现冲突。继承集中的属性只能声明一遍。如果多次声明就会导致冲突,说明模型为非良性结构。(这一限制不是基于逻辑推理,而是为了防止出现必须用路径名区分属性时可能产生的异义)
操作可以被多次声明,只要声明相同(方法可以不同),或者子声明强化了某个继承声明(如将子声明为队列或增加它的并行状态数)。子声明的方法取代(重载)祖先的方法声明,不会有冲突。如果从没有祖先关系的两个元素中继承到了不同的方法,则会出现冲突,说明模型为非良性结构。
讨论
泛化是元素之间的类元关系,它解释了一个元素是什么;继承是连接共享递增声明,从而形成元素的完整声明的机构,这两者是不同的,但有着密切的关系。在泛化关系上应用继承机构,可以实现说明的分解和共享,以及多态行为。这是UML和多数面向对象语言使用的方式,但是某种程序设计语言还可能采用其他方法。
168.初始状态(initial state)
转换的目标状态是组成状态的边界时,用来指明其默认起始位置的伪状态。
见复合状态(composite state)、创建(creation)、入口动作(entry action)、 初始化(initialization)、结合状态(junction state)
语义
为了实现封装,应该尽可能地将组成状态的外部视图与内部细节分开。从外部看,组成状态是隐藏了内部结构的不透明实体,从外部视图看,转换的起止点都是状态自身。从内部视图看,它们连到状态内的子状态。
初始状态是一个伪状态,它代表了进入转换与组成状态边界的结合点。它不是真实的状态,不能保留控制权,它只是说明控制应该转向哪里的语法表达式。初始状态必须要有一个出去的无触发转换(没有事件触发器的转换,因此遇到初始状态可自动有效)。完成转换连接到组成状态中的一个真实状态上。完成转换上可以有动作,该动作在状态的入口动作(如果有)之后遇到状态时执行。除了入口活动(在所有入口处执行,否则缺省)之外,它还允许动作与缺省入口关联。这个活动可以访问隐含的当前事件--即由最终使得转换转向初始状态的转换中的第一片段触发的事件。
初始状态不能有带触发事件的向外转换,进入转换与进入其组成状态的转换是一样的,也应该避免,应该将这种转换与组成状态相连。
通常初始状态上的转换是无监护条件的,因而必须是来自初始状态的唯一转换。多个向外的转换将带有监护条件,这些条件必须涵盖所有的可能性(或者把某个条件设为"其他")。关键是控制权必须马上离开初始状态。它不是真实的状态,必须激活某个转换。
类的顶级状态中的初始状态,代表了类的新的实例的创建。当执行它的向外转换时,隐含的当前事件是创建对象的事件,它具有由构造操作传来的变元值。这些值可供向外转换上的活动使用。
对象创建
一个类的大多数组成状态的初始状态都很类似,它可能带着标有关键字《create》的触发事件,以及带参数的有名字的触发事件。可以有多个此类转换具有不同触发事件。当生成类的对象实例时,触发与其创建操作相应的转换,该转换从调用创建操作处得到变元值。
表示法
组成状态中的初始状态表示为小的实心圆,其上可以有向外转换箭头。一个组成状态中只能有一个初始状态(直接)。但是嵌套的组成状态中可以有多个组成状态。
举例
图13-108中,我们从状态X开始,出现事件e之后,激活转换并执行活动a,转换指向状态Y,执行入口活动b之后,初始状态成为活动状态。随后立即进行外向转换,执行活动c并进入状态Z。
如果系统处于状态X时发生事件f,则激活另一个转换执行活动d,转换直接到达状态Z,这一过程中不包括初始状态,因为控制权转交给Y,所以要执行活动b,但不执行活动c。
图13-109中的初始状态带有分支。假设系统开始于X状态,当事件e出现时,执行活动a,系统则进入状态Y并完成入口活动b,控制权转给初始状态,测试当前对象的size属性;如果值为0,控制转入状态Z;如果值不为0,控制转入状态W。
图13-108 初始状态
图13-109 带有分支的初始状态
169.初始值(initial value)
说明对象初始化之后某一属性值的表达式
见默认值(default value)、初始化(initialization)。
语义
初始值是属性所带的一个表达式。表达式是一个文本字符串,可以用某种语言进行翻译。当对带有此属性的对象进行初始化,用给定的语言和系统当前值计算该表达式。计算结果用于对新对象中的这一属性进行初始化。
初始值是可选的,如果没有,则属性声明没有指出新生对象所带的值(模型的其他某个部分将提供这一值)
注意,明确的对象初始化过程(例如构造)可以忽略初始值表达式或者覆盖属性值。
类范围属性的初始值只在执行开始时使用一次,UML没有规定不同类范围属性初始化的相对顺序。
170.初始化(initialization)
为新生成的对象赋值--即其属性、所属关系的连接和控制状态。
语义
概念上,新对象的创建是一步完成的,但将其理解为两步会更容易理解:创建和初始化。首先给出空壳对象,它有适当的结构和属性位置,并赋予了标识符,标识符可以用不同的方法实现,例如包含对象的存储块地址,或内部计数器。总之,标识符在系统中是唯一的,可以作为查找和访问对象的句柄。到此为止,对象仍然不是合法的--它违反其值和关系上的约束。下一步是初始化,计算给出的初始值表达式,将结果加入相应的属性位置。创建方法可以显式计算属性值,从而重载默认的初始表达式,结果值必须满足类的约束。创建方法还可以生成包含新对象的链接,它们必须满足与类有关的关联多重性的要求。初始化完成后,对象成为合法的,并应符合其类的所有约束。初始化完成后,属性或其可变性属性为frozen或add only的关联不能再变化,直到对象被销毁为止。这个初始化的操作是原子的,不能被打断,也不能中途离开。
171.实例(instance)
带标识符和值的独立实体。描述符说明具有相似特性的实例集的形式和行为。实例的标识符和值符合描述符的说明,模型中出现的实例主要是符合描述符模型的实例
见 描述符(des criptor)、标识(identity)、链接(link)、对象(object)。
语义
实例带有标识符。换言之,在系统运行的不同时刻,即使实例的值改变了,该实例可由不同时间点的同一实例来标识。任何时候,实例的值可以是数据值或执行其他实例的指针。数据值是退化形式,其标识符与其值相同,从另一个角度看也可以认为它没有标识符。
除了标识符和值以外,每个实例带有描述符,它用来约束实例可能取的值。描述符是说明实例用的模型元素,UML中大多数模型元素有这样的双重特征,多数元素的主要内容就是各种描述符。此模型的目的就是用系统的实例和实例的值来说明系统可能的不同取值。
每种描述符描述一种实例。对象是类的实例;链接是关联的实例。用例说明可能的用例实例;参数说明可能的变元值,如此类推。某些实例没有家族名,除非正式设置,往往被忽略,但这并不排除它们的存在。如一个转该描述一条执行轨迹中状态的可能出现,若系统中每个实例都是模型中的某个描述字的实例,并且实例集满足模型中所有显式和隐式约束,则系统值合法。
模型说明系统可能的取值以及执行过程中从一个值变到另一个值时系统的行为。系统的值是系统内所有实例以及它们各自值的集合。
模型中的行为元素说明系统及其中的实例如何从一个值转变到另一个值。实例标识符的概念对这种说明十分重要。每个行为步骤以其先前值说明了少数几个实例值的变化。系统中其余的实例值不变。例如,对象上的局部操作,可以用对象每个属性新值的表达式来表示,同时系统其余部分不变。非局部性的函数可以被分解为几个对象上的局部函数。
注意,执行系统中的实例不是模型元素,通常,它们甚至不算是模型的组成部分。模型中的实例作为典型结构和行为的解释或例子出现,是系统取值或运行历史轨迹的简短捕捉,这对于人的理解是很有用的,但是它们通常不定义任何东西,只是指示许多可能的取值。
直接实例 每个对象都是某个类的直接实例,也是这个类的祖先的间接的实例。对于其他可泛化元素的实例也是一样,如果一个类说明某个对象且此类的后代不再说明这一对象,该对象就是此类的直接实例。多重类元中,一个实例可以是多个类元的直接实例,这些类元之间没有互为祖先关系。某些执行语义下,由一个类元指明实现类,其他指明角色或类型。完整描述符描述了实例的所有属性、操作、关联和其他特征,它们可以从直接类元处得到,也可以从祖先处继承得到。多重类元时,完整描述符是每个直接类元的属性的结合。
创建 见实例创建方式描述的实例化。
表示法
虽然描述符与实例是不同的,但是它们有许多共同的特点,包括相同的格式(因为描述符必须说明实例的格式)。因此,为描述符--实例对选择表示法时应尽可能直接地体现二者的对应关系。实现的方法不多,每种各有优缺点。UML中,将二者用同样的几何符号表示,并给实例元素的名字字符串加下划线。
虽然图13-110表示的是对象,但下划线表示法一样适用于其他实例,如用例实例、构件实例和节点实例。
因为模型中的实例是作为例子出现的,通常仅包括与具体例子有关的细节。例如,不必列出完整的属性表;如果关注的是其他东西(例如对象间的信息流),甚至可以忽略整个属性表。图110 描述符与实例
172.某描述符的实例(instance of)
实例及其描述符之间的关系。
见实例(instance)。
173.可实例化(instantiable)
可以有实例,同义词:具体(concrete)。
见抽象(abstract)、直接实例(direct instances)、可泛化元素(generalizable element) 。
语义
可泛化元素可以被声明为抽象的或是可实例化的。如果它们是可实例化的,就可以创建直接实例。
174.进行实例化(instantiate)
创建描述符的实例。
见实例化(instantiation)。
175.实例化(instantiation)
新模型元素实例的创建。
见初始化(initialization)。
语义
实例是在运行时由原始创建活动或创建操作创建的。首先为新的实例生成标识符,接着按其描述符的说明生成数据结构,最后由描述符和创建操作者对它进行属性值的初始化。
实例化使用依赖关系表示了创建实例的类或包含此操作的类与实例化对象所属类之间的关系。
对象 当对象被实例化(创建)时,被赋予标识符和存储区,对象被初始化。对象的初始化定义了其属性值、关联和控制状态。
通常,一个具体类有一个或多个类范围的构造操作,其目的是创建该类的新对象,所有构造操作潜在地创建了一个新的未加工的实例,该实例随后由构造操作初始化。未加工的实例生成之后,即拥有其描述符所规定的格式,但其值未经初始化。因此,实例初始化之前不能被系统所使用。
链接 类似地,链接由创建活动或操作创建。它通常是相应类所带的实例范围操作,而不是关联元素自身的构造操作(虽然某些情况下这也是一种可能的实现技术)。同样有一个创建对象之间新链接的潜在的操作,如果一组对象间已存在同类关联,则操作无效(因为关联的内容是一个不能有迭代值的集合)。对普通关联无须进一步操作,但是关联类的链接还须对其属性进行初始化。
用例实例 用例实例化意味着创建用例实例,而且用例实例开始执行。用例实例可能先暂时执行有扩展关系或包括关系的其他用例,而后再返回原始用例。当执行到相应用例末端后,用例实例将结束。
其他实例 其他描述符的实例也可以通过类似的两个步骤生成:首先创建未加工的实例,建立标识符并分配数据结构;按着对新实例的值初始化,使之满足相应约束。例如,活动是调用操作的直接结果。
创建实体的确切机构是运行时环境的任务。
表示法
实例化依赖关系表示为虚线箭头,从执行实例化的类或操作指向被实例化的类;箭头上标明构造类型《instantiate》
讨论
有时用实例化来表示将模板绑定,从而生成绑定元素。但是绑定关系更适合于这种情况。
176.内涵(intent)
描述符结构和行为特点的正式描述。对比:外延。
见描述符(descriotor)。
语义
描述符(如类和关系)既有描述(内涵),又有其描述的实例集合(外延)。内涵的目的在于用可以执行的方式对实例的结构和行为进行说明。
177.交互(interaction)
说明对象或其他实例是如何传递消息的,交互在合作的语境中定义。
见交互图(inreraction diagram)。
语义
合作中的对象或其他实例为了完成某一任务(如执行一个操作)而通过信息交换来进行通信。信息可以包括信号、调用。为完成一个特定目的而进行的信息交换的模式称为交互。
结构
交互是一组对象之间为完成某一任务(如完成一个操作)而进行的一系列信息交换的行为说明。为了说明交互,必须先说明合作--即定义交互的对象及其关系。而后说明可能的交互序列。可以用带有条件(分支或条件信号)的单描述符或者多描述(每个描述符说明可能的执行路径中的一条),合作行为的完整描述可以用状态机实现,其状态就是操作或其他过程的执行状态。
表示法
交互用顺序图或合作图表示,两种图都能表示合作的执行。顺序图明确地表示了合作的行为,包括信息的时间顺序以及方法激活动的显式表示。但顺序图只表示参与的对象而不表示它们与其他对象的关系和属性。因此,它不能全面表示合作的语境视图。合作图表示交互的完整语境,包括对象及其关系,因此对设计更为适用。
178.交互图(interaction diagram)
应用于多种视图的着重于对象交互的表现方式。包括合作图和顺序图,二者与活动图密切相关。
见合作(collaboration) 、交互(interaction)。
表示法
交互图中表示对象之间交互的方式。交互图在同一个信息基础上发展为不同的形式,各自有不同的侧重点。它们是:顺序图、合作图和活动图。
顺序图表示按时间排序的交互,着重表现参与交互对象的生命线和它们交换的信息。顺序图不表示对象之间的链接。根据目的不同,顺序图有不同的形式。
顺序图有一般形式(说明所有可能的序列),还有实例形式(说明与一般形式一致的一个执行序列)。在没有分支与循环的情况下,两种形式是同构的,描述符是其实例的原型。
合作图表示执行操作的对象间的交互。它类似于对象图,表示了实现高层操作所需的对象和它们之间的链接。
信息的时间顺序用信息流箭头上的序号表示。同步和异步信号都可以用相应的语法表示。顺序图中用箭头的几何顺序代表时间顺序,因此不用序号。有时在顺序图中使用序号是为了方便,或为了允许切换到合作图。
顺序图和合作图用不同的方式表示了类似的信息。顺序图表示信息的确切次序,更适合于实时说明和复杂的情形。合作图表示对象之间的关系;更适合于理解对象的全部作用和过程设计。
讨论
活动图表示执行高层操作中的过程步骤。它不是交互图,表示的是过程步骤之间的控制流而不是对象之间的控制流。侧重点在于过程中的步骤。它不表示到目标类的操作的任务。活动图构造了表示执行中状态的状态机。活动图中的许多特殊图标与UML基本结构等效,只是受限于附加的限制,提供良种表示可便于使用。
179.交互视图(interaction view)
表示对象之间为完成某任务而进行信息交换的视图,其中包括合作和交互,用合作图和交互图表现。
180.接口(interface)
说明元素特有行为的命名操作集。
见类元(classifier)、实现(realization)。
语义
接口是类、构件或没有内部结构说明的其他实体(包括包等汇总单元)的外部可见的操作的描述符。每个接口仅描述实际类的行为的有限部分。一个类可以支持多个接口,效果上或互斥,或覆盖。接口没有实现,缺少属性、状态和关联;它只有接收的信号和操作,接口可以有泛化关系,子接口有其祖先的全部操作和所接收的信号。接口可有泛化关系。子接口包括其父所有操作和信号,但可以有附加操作。接口与没有属性、方法只有抽象操作的抽象类等价。接口中的所有操作都是公共可见的(否则,不可能引用它们,因为接口没有所谓的"内部"来引用它们)。
下列扩展定义说明
.接口是用于说明类或构件的某种服务的操作集合。
.接口用于为一组操作命名,并说明其信号和效用,接口着眼于服务的效果,而不是结构。接口不为其中的操作提供实现,接口的操作列表中还可以包括类可以处理的信号。
.接口用于说明服务者为其他模型元素提供的服务。接口为一组操作命名,这组操共同实现系统或部分系统的部分行为。
.接口定义了类或构件提供的服务,它定义的服务由类或构件实现。因此接口跨过了系统的逻辑和物理的界限。一个或几个类(可能是某个构件子系统的部分)可以提供一个接口的逻辑实现。一个或几个构件可以提供符合同一接口的物理包。
.如果类实现一个接口,则它必须声明或继承接口的所有操作,它也可以有另外的操作(见实现)。如果一个类实现多个接口,它必须包含所有接口的操作。多个接口中可以有相同的操作。如果标志相符合,就一定是同一操作,否则会发生冲突,说明系统为非良性结构(实现可以采用语言特定规则来匹配标志。例如C++中忽略参数名和返回类型)。接口不声明类的属性或关系;它是类的实现的一部分。
.接口是可泛化元素,子接口继承祖先的全部操作并可以有新的操作。实现被视为行为继承;类继承其他类元的操作,而不是结构。一个类可以实现另一个类。起说明作用的类就象是接口,只有操作部分影响关系。
.接口参与关联。接口不能作为关联的出发点,但可以是关联的目标;只要该关联只对接口有导航性。
表示法
接口是一种类元,可以用带关键字《interface》的矩形表示。接口支持的操作列在操作分格中。操作分格中还可以有信号(带构造类型《signal》)。信号也可列在独立分格中。属性分格可以省略,因为它总是为空的。
接口还可以表现为小圆圈,接口名字在圆圈下方。圆圈符号用实线与支持接口的类或其他元素相连,它还可以连向高层的单元,例如包含类的包。这说明类支持接口类型的全部操作(可能更多)。圆圈表示法不表示接口支持的操作,用完整矩形表示法表示操作列表。虚线将接口和使用其操作的类连起来,箭头指向圆圈。虚线箭头表示类使用接口中声明的操作,但用户类并不需要接口中所有的操作。服务通常用效果测试来说明,如果提供者提供一列接口中的操作,则满足客户的需求。
实现关系用带实心三角形箭头的虚线表示(虚线泛化关系标志),箭头从类指向它支持的接口。这与表示通过实现类来实现类型的方法相同。事实上,这种符号可用于任意两个类元之间,表示客户(箭尾)支持提供者(箭头)定义的所有操作,但不必支持服务者的数据结构(属性和关联)
举例
图13-111是处理有价证券财政的商业构件的简化视图。FinancialPlanner是记录个人花费与投资的个人财政应用程序。它要有刷新有价证券价格的能力。MutualFundAnalyzer仔细检查公共基金,需要刷新当前有价证券价格的能力。刷新价格的能力用接口Updateprice表示。有两个构件实现该接口,用将它们连到接口符号的实线表示。构件ManualPriceEntry允许用户人工输入选定有价证券的价格。QuoteQuery通过调制解调器或网从报价服务器上得到有价证券的价格。
图13-111 接口的提供者和客户
图13-112表示作为类的关键字的接口的完整形式。该接口有两个操作--询问有价证券的价格并获得值,提交有价证券价格表并接受改动的价格表,在此例中,QuoteQuery用实线箭头与接口相连,这与上一图中关系相同,只是更确切而已。
图中还有一个新的接口PeriodicUpdatePrices,它是原始接口的子。它继承了两个原始操作并增加了一个操作,用请求定期自动刷新价格。该接口由构件QuoteServer实现。它也实现了QuoteQuery中的两个操作,但方法不同。它不共享QuoteQuery的实现(本例中),因此不继承它的现实。
图13-112表示了接口继承和完全继承的区别。后者包含前者,但子接口可以用与父接口不同的方法实现,QuoteServer支持QuoteQuery实现的接口(即UpdatePrices),但不能继承QuoteQueryde 实现(通常,同时继承实现和接口更为便利,所以两种结构常常是等同的)
接口可以包括它能处理的信号列表(图13-113)。
图13-112 完整接口表示
图13-113 带有信号的接口
接口用于定义类、构件的行为,而不限制其实现。这样,允许将接口继承与实现继承分开,如JAVA语言的声明。
181.接口继承(interface inheritance)
继承父的接口而非其实现或数据结构。支持接口而不继承实现的设想通过用实现关系来建立模型实现。
注意,在UML中,泛化关系隐含了接口和实现继承。只有用私有继承才能保证只继承实例而不继承接口。
见实现继承(implementation inheritance)、继承(inheritance)、私有继承(private inheritance)、实现(realization)。
182.接口说明(interface specifier)
对关联类要求的行为的说明,这种行为用于满足关联的内容。它包括指向说明所需行为的接口、类、或者其他类元的指针。
见关联角色(association role),角色名(rolename),类型(type)。
语义
通常,关联类的功能不仅支持一个关联。例如,类可能参与其他关联,其行为是所有关联所要求的行为之和。应该更明确的说明一个类中支持一个关联的功能。接口说明符是关联端上的一个类元,用于说明支持此关联所用的功能,而不考虑目标类中供其他关联使用的功能。
接口说明符不是必须的,多数情况下,一个类只参与一个关联,没有多余功能。如果省略接口说明符,关联拥有对关联类全部功能的访问权。
说明符可以是类元集合,每个类元都说明目标类必须支持的操作。目标类必须满足所有要求,有可能比说明符要求的还高。
表示法
接口说明符语法
角色名:iname表。
iname是代替角色名的接口或其他类元的名字。如果有多个说明符类元,它们的名字用逗号隔开。
举例:
图13-114中,Server层将请求存入一个Array类中,为此,它仅需要Queue类的功能,不随机访问信息。实际的Array类满足接口说明符Queue(包括一个队列功能的一个数组)的需求,Monitor用一个Array来表示请求的状态,使用Array的全部功能。
图13-114 接口说明
讨论
使用角色名和接口说明等于创建一个合作,其中仅包含一个关联角色和两个类元角色,其结构由原始关联的角色名和角色类元定义,因此合作使用关联和类。原始类必须符合接口说明(可以是接口和类型)
183.内部转换(internal transition)
状态所带的有活动的转换,但它不会引起状态改变。
见状态机(state machine)。
语义
内部转换允许事件引起活动同时不改变状态,它有初始状态而无目标状态,一旦被激活,转换上的活动将被执行,但状态不会改变。因此,不执行入口或出口活动。从这方面来看,它与自转换不同,自转换会导致退出嵌套状态,并引发出口或入口动作。
表示法
内部转换用文字条目列在状态的内部转换分格中,条目与外部转换的文本标签语义相同。因为没有目标状态,不需要使用箭头。
事件名字 / 活动表达式
entry、exit、do和include是保留字,不能作为事件名,它们用来声明入口活动、出口活动、活动执行或子机构的执行。这些特殊活动使用内部转换语法是为了更明显。它们不是内部转换,这些保留字也不是事件名。
图13-11展示表示法。
讨论
内部转换可被视为一种"中断",它引发一个活动但不改变当前状态,因此不激活出口或入口动作。最好办法是通过将一个内部转换连到一个组成状态来建模一个活动,该活动必须在一些状态中出现,但不得改变状态的活动状态--例如表示帮助信息或事件出现次数计数器。不宜于建模夭折或异常,它们应该用转入新状态的转换来建模,因为它们的出现与当前状态不符。
184.不变量(invariant)
一个必须永远为真的约束(或者至少在所有活动完成时为真)。
语义
不变量是一个必须在无活动操作的任何时刻为真的布尔表达式。它是一种声明而不是可执行的语句,根据表达式形式的不同,它可以或不可以被事先确定。
见前驱条件(precondition)、后继条件(postcondition)
结构
不变作为约束,带有构造类型《invariant》。
表示法
后继条件可以表示为带《invariant》关键字的注释。注释附在类元、属性或其他元素上。
185.迭代表达式(iteration expression)
产生迭代用例集的表达式。每个迭代用例指定迭代中一个活动的执行。迭代用例可以包含对迭代变量的赋值。每个迭代用例只执行活动一次。
见消息(message)
语义
迭代表达式代表条件的或迭代的执行。根据包括的条件,表示0个或多个消息。选择有:
*[迭代子句] 一个迭代
[条件子句] 一个分支
一个迭代代表一个消息序列,迭代子句表示迭代变量和测试细节,但可以省略(在未确定迭代条件的情况下)。迭代子句用伪代码或实际的程序设计语言表达。UML没有说明其格式。可以是
*[I:=1……n]
条件所代表的消息的执行与否依赖于条件子句是否为真。条件子句用伪代码或程序设计语言表达。UML没有说明其格式,可以是
[x > y]
注意,分支与不带星号的迭代表示法相同,可以将它视为只出现一次的迭代。
迭代表示法假设迭代中的消息顺序执行,它们也可能并行执行,其表示法为星号加双竖线。例如:
*[I:=1……n]|| q.calculateScore()
注意在嵌套控制结构中,迭代表达式在序号内部层次中不迭代,每层在其语境中定义自己的迭代。
186.迭代开发(iterative development)
包括一系列步骤的系统开发,或称为迭代。每个迭代都比前一个更接近所希望的系统。每一步的结果必须是可执行的系统,以供执行、测试和调试。迭代开发符合于递进式开发。在迭代递进式开发中,每个迭代为上一个增加了新的能力。能力增加的顺序要考虑到迭代平衡和尽早发现重大风险。
见开发过程(development process)。
187.结合(join)
状态机活动图或顺序图中的一个位置,在此处有两个或以上并列线程或状态归结为一个线程或状态;一个结合或非分支。反义词:分支
见复杂转换(complex transition)、复合状态(composite state)。
语义
结合是有多个源状态和一个目标状态的转换。一旦所有源状态处于活动且发生触发事件,就执行转换,目标状态为活动的,源状态必须在并行组成状态的不同区域中。
表示法
结合表示为有多个转入箭头和一个转出箭头的粗线。它可带有转换标签(监护条件,触发事件和活动),图13-116是并行组成状态中的来自多个状态的一个显式结合。
讨论
见合并(merge)。
188.结合状态(junction state)
状态机中作为一个综合转换一部分的伪状态。它在转换执行中不打断运行至完成步骤。
见分支(branch) 、合并(merge)。
语义
状态机中的转换可以从源状态跨过几个组成状态的边界到达目标状态。执行这种转换时会激活一个或多个出口/入口活动。某些情况下,有必要将转换上一个或多个活动与嵌套状态的出口/入口活动交汇。对只有一个单一活动的简单转换而言,这是不可能的。
使多个触发有单一输出或允许一个触发有多个带监护条件的输出将会十分便利。
结合状态作为一种伪状态,使得从多个转换段中建立一个综合转换成为可能。结合状态可以有一个或多个转入段和一个或多个转出段。它不能有内部活动、子机构,或者有触发事件的向外转换。它是构建转换用的伪状态,因而不能处于"活动"的状态。
结合状态可以构建源自多个片断的转换。结合状态链中只有第一个段可以有触发事件,但每个段都可以有监护条件。其后段必须无触发。有效的监护条件是所有单个监护条件的结合体。除非所有条件被满足,否则转换不会开始。换言之,状态机不会处于结合状态。
如果多个转换进入一个结合状态,它们各自可以有不同的触发,也可无触发。通过结合状态集的每条路径代表了一个不同的转换。
向外的转换也可以有监护条件。如果有多个向外转换,每个必须有独自的监护条件,这就是分支。
向外转换可以附带活动(结合状态可以有一个内部活动,但它等价于将一个活动连到向外转换)。一旦所有监护条件满足,活动将被执行。转换不能部分激发而停在结合状态,必须到达某个常规状态。
当转入的转换激活后,向外的转换会立即被激活,随即执行附带的活动。转入和向外的转换是一个原子步骤(运行到结束步骤)的部分--它不能被任何活动或事件中断。
表示法
状态机中用小圆圈表示结合状态。它没有名字,可以带有向内和向外的转换箭头。
举例:
图13-117是状态S到T的两个完整转换--由事件f触发的单段转换和事件e触发的多片断转换。图中还表示了入口/出口活动。
注意,转换线上的活动标签的位置没有意义。如果活动d画在状态x中,它将在x退出y进入之前执行。因此,d应画在转换上的最外面的位置.
图13-179和图13-184表示了其他例子。
见控制图标等状态图和活动图中可能出现的符号
189.关键字(keyword)
关键字是为没有独立语法的模型元素类元用的文字。
见图形标志(graphic marker)、构造类型(stereotype)
表示法
关键字用于没有单独表示法的内置模型元素和用户定义的构造类型。通常将关键字写在书名号内。
《关键字》
如果带关键字的符号有一定大小,则将关键字打在符号边界内。
某些预定义关键字在本文中说明,并用保留字的方式表示。其他可供用户作为构造类型使用。不能使用与预定义关键字相同的构造类型。
讨论
容易区别的符号是有限的,因此UML表示法用文本关键字来区别同一主题下的不同变体,包括基类的元模型子类、元模型基类构造类型,以及表元素组。对用户而言,元模型子类和构造类型间的元模型区别并不重要,但它对工具制造者和实现元模型建立者而言是重要的。
190.标签(label)
在图中使用字符串的一种方法,仅仅是表示法。
见图(diagram)。
表示法
标签是图中在逻辑上附属于另一个符号的图形字符串。通常将字符串标在符号边上或封闭区域内来表示这种附属关系。对某些符号而言,标签位置是确定的(如在线下)。而对多数符号而言,标签必须靠近线或目标。编程工具可以维持标签和图形符号之间的内部联系,这样即使标签和图形符号分开表示,二者在逻辑上也是相连的。在最终视图中必须都表示清楚,以保证符号和标签连接关系不会产生混淆。虽然图中并不一定能完全清楚的表示附属关系,但这种关系在图的结构层次上是清晰无异议的。工具可以用其他方法表示标签与符号之间的附属关系(如着色线或匹配元素闪烁)。
191.语言类型(language type)
用编程语言的语法定义的匿名数据类型。
见数据类型(data type)。
语义
类型是一种作为由编程语言翻译成数据类型的表达式。它可以为属性、变量、参数的类型。它没有名字,不能用于声明新的数据类型。
例如,c++数据类型"erson*(*)(Contract*,int)"可被定义为C++语言类型。
语言类型的目的是编程语言中的实现。更多的逻辑关系应该用关联实现。
192.层(layer)
将模型中同一抽象层次的包分组的一种结构模式,每个层在某个实现层次上代表一个虚拟世界。
193.叶(leaf)
在泛化层次结构中,没有子的可泛化元素,它必须是供使用的具体(整体实现的)实体。
见抽象(abstract)、具体(concrete)。
语义
叶属性声明一个元素必须为叶。如果声明了叶的子,说明模型为非良性结构。其目的是保证类不被修改。例如,类中行为必须完整的,这样才有实际意义。叶声明还允许将系统不同部分的编译分开,它保证方法代码不被重载,以及方便方法代码的嵌入。叶属性为假的元素可能实际上是叶,但它可以在将来修改模型时生成子。视为叶或者被限定为叶不是基本语义属性。
194.生命线(lifeline)
顺序图中的虚线,用来表示对象在一段时间内存在,此线与时间轴平行。
见顺序图(sepuence diagram)。
语义
生命线表现了对象存在的时段。对象在拥有控制线程时激活--即作为线程的根时。被动的对象在控制线程通过时暂时存在--被外部调用时。后者称为活动,它的存在时间包括过程调用下层过程的时间。
表示法
对象或类元在顺序图中表示为垂直虚线,称为生命线。生命线表示对象在特定时间段内存在。
生命线间的箭头代表对象之间的消息,指向生命线箭头表示对象接收信息,由一个操作完成,箭尾表示对象发送信息,由一个操作激活。生命线之间箭头排列的几何顺序,代表了消息的时间顺序。
如果对象在顺序图表示的时间段内创建或消亡,其生命线就在相应时间点开始或终止。否则,生命线贯穿图的始终。对象符号画在生命线上。如果对象在图中被创建,则对象符号画在创建它的消息上,否则,对象符号画在任何消息箭头上。如果对象在图中被销毁,用大X表示销毁,X或者标在导致销毁的消息的箭头上,或被销毁对象的最终返回消息(自毁)上。转换开始时存在的对象画在图的顶部(第一个箭头上方)。转换结束后仍存在的对象,生命线画过最后一个箭头。
生命线可分为两条或是更多,以表示条件控制。每条轨迹对应消息流的一个分支。生命线也可在某一点结合,见图13-162。这种表示法易引起混淆,应小心使用。
对象永久或暂时活动的时期用一条实线表示生命线。第二条双线表示迭代。祥见激活。因为主动对象总是活动的,有时省略双线。
生命线被状态符号中断表示状态转换,这与合作图中的成为转换相应。指向状态的箭头表示引起状态变化的消息。见图13-163
195.连接(link)
对象引用元组,是关联或关联角色的实例。
语义
连接是两个或多个对象之间的独立连接,它是对象引用元组(有序表),是关联的实例。对象必须是关联中相应位置处类的直接或间接实例。一个关联不能有来自同一关联的迭代连接,即两个相同的对象引用元组。
作为关联类实例的连接除了对象引用元组外还可以有属性值表。不允许具有相同元组对象引用的迭代连接,无论其上的属性是否不同。连接的标识符来自对象引用元组,它必须是唯一的。
连接可以用于导航。换言之,连接一端的对象可以得到另一端的对象,也就可以发送消息(称通过联系发送消息)。如果连接对目标方向有导航性,这一过程就是有效的。如果连接是不可导航的,访问可能有效或无效,但消息发送通常是无效的,相反方向的导航性另外定义。
合作中,关联角色是语境有关的暂时的类元之间的关系,关系角色的实例也是连接,其寿命受限于与合作的长短。
表示法
连接表示为对象间的路径--一个或多个相连的线或弧。在可变关联中,路径是两端指向同一对象的回路。表示实例的名字有下划线。连接没有实例名,它的标识符来自相关的对象,因为实例没有多重性,连接也没有多重性。多重性是说明可以存在的实例数目的标识符。连接角色上可以表示其他关联修饰(聚集、组成、导航)。
连接上可以表示限定词,限定词的值可以表示在盒中,
图13-118有常规连接和限定词连接.
连接还可以表示关联的属性,如导航方向、聚集、组成、实现构造类型和可视性。
N一维连接 n维连接用菱形表示,引出到每个参与对象的路径,其他表示与上文相同。
讨论
对象图如何表示依赖关系?通常,依赖代表类之间的关系并在类图中表示,而不在对象图中表示。过程变元、局部变量和操作调用应作为实际的数据类型出现而不仅仅是依赖关系。因此,它们可以表示为连接调用者要得到目标对象过程的指针--这就是连接。有些连接是合作中关联角色的实例,如变元和局部变量。记住:依赖与类相关,而不是与各个对象相关。
196.连接端(link end)
关联端的实例。
197.列表(list)
由另一个模型元素拥有且嵌套其中的长度可变的有序模型元素序列。
见类元(classifier)、状态(state)。
语义
类元有许多子列表,包括属性,操作和方法。状态有内部转换列表。其他元素有其他元素列表。每种列表独自说明。通常用这种技术说明嵌入表的属性。除了属性和操作列表外,可用其他列表说明预定义或用户定义的值,如责任、角色或修改历史。UML没有定义这些可选列表,由用户定义的列表操作依赖于工具。
嵌入列表和其中的元素要么属于包含类,要么属于其他包含元素。多个包含元素不能共享所有权。其他类可以访问列表中的元素--例如通过继承或关联,但只有直接包含元素有所有权和修改权。这些列表元素连同包含元素一同存储、复制和销毁。
列表元素的顺序由建模者决定。这种顺序会很有用--例如,可作为生成编程语言声明序列的代码生成器。如果建模者不关心顺序,可能因为模型处于分析阶段或因为语言与顺序无关,这种顺序虽仍在存在但可以忽略。
表示法
嵌入列表在独立的分格中表现为字符串列表,每个元素对应一行字符串。每个字符串是特征的编码表示,如属性、操作、内部转换等等。编码种类由每种元素说明。
排序 字符串的顺序和列表中的元素的顺序一致,但内部存储顺序可能并非如此,字符串存储可能依赖于某种内部属性,如名字、可视性或构造类型。注意:每项仍维持它在基本模型中的顺序。排序信息仅仅在视图中忽略。
省略号 省略号(…)作为列表末尾的元素表示模型中还有符合条件的元素,但未在表中列出。在其他视图中,可能列出这些元素。
构造类型 列表元素可以有构造类型。构造类型关键字写在列表元素前面。
属性字符串 属性字符串说明元素的属性。在元素之后的大括号内,用逗号分隔列出属性和约束。
组属性 一组列表元素可以有属性或构造类型。如果单独的一行中出现构造类型、关键字、属性字符串或约束,则此行不表示一个列表元素。而是此后所有元素共同的属性,如同它们直接作用于每一行一样。默认效果持续到出现表中另一组属性为止。插入带有一个空关键字(《》)的一行可以撤销所有组属性,但将不受限于组属性的所有项置于表头,会更明了些。
图13-119表示了作用于多个元素的构造类型。
注意:组属性只是一种方便的表示法,每个模型元素仍带有各自的属性值。
分格名字 分格可以有名字,用特殊字体(如小写黑体)表示,标在分格顶上。如果有省略或新增加的用户自定义的分格,这种标志就十分有用。对类而言,预定义的分格名为attributes和operations。用户定义的分格可能是requirements。类的名字分格必须有,因此不需要也不允许分格名字。图13-119和
表示选项
排序 工具可能按存储顺序列出表元素。此时,看不到元素的继承顺序。顺序基于某些内部属性,不表明额外建模信息。典型排序包括字母顺序、构造类型顺序(构造函数、析构函数,以及一般方法),按可视性排序(公共、保护到私有),等等。
筛选 列表元素可以按照某些规则筛选。选择规则的说明是工具的责任。如果筛选列表为空,说明没有符合要求的元素,但原始表可能或不可能包含不满足规则从而不可见的其他元素,工具应负责是否说明局部和全部筛选以及如何说明。还可以用单独的图来对此说明。
如果省略一个分格,则不能确定其中的元素的存在与否。空的分格说明没有符合筛选条件的元素。
注意:属性也可以通过组成表示(图13-71)
198.位置(location)
一个运行时实体在某环境中的物理放置,如分布式环境中的对象或分格。在UML中,位置是分散的,位置单位是节点。
见构件(component)、节点(node)。
语义
位置的概念需要实体存在空间的概念。UML没有建立三维空间,而是提供了由通讯路径连接的拓扑模型空间。节点是运行时实体可以存在的计算资源。节点之间用通讯路径相连,实体的定位就是分配节点指针。在节点上,有些实体存在于其他嵌入实体内。例如,对象存在于构件或其他对象中,这些实体的位置就是其包含实体的位置。
对象或构件实例可以移动到新的位置上。这可以通过"成为(become)"关系表示,"成为"意味着在某一时刻第一个实体被第二个实体代替,而第二个实体原来在另一个位置上。
表示法
实体(包括对象、构件实体和节点实体)的位置在另一个实体之内可以用物理嵌套表示,
如图13-121所示。包含关系也用组成箭头表示。或者实例可以有一个location标记的属性,其值为包含元素的名字。
如果对象在交互中移动,它可以表示为多个版本,版本间用become转换相连。见图13-121。become箭头可以有序列号,说明对象移动的时间。每个对象符号代表时间段对象的一个版本。消息必须与正确的对象版本相连(图13-117)。
199.许多(many)
多重性0 ..* 的缩写--0个或无限多个。换言之,大小不限。
见多重性(multiplicity)
200.成员(member)
类元的已命名结构化继承组织的名字,可以是属性、操作或方法。每个类元可以有0个或多个各种成员。特定种类成员的列表以字符串表的形式表示在类元符号的分格中。
见列表(list)。
201.合并(merge)
状态机中的一个位置,两个或多个可选的控制路径在此汇合或"无分支"。反义词:分支。
见 结合状态(junction state)
语义
合并是指两个或以上控制路径汇合的情况。在状态机中,一个状态有多个转入转换。没有提供合并的特定模型构造。如果它是单一运行至完成步骤的一部分,则可以由结合状态表示。
表示法
在状态图、顺序图或活动图中。合并表示为带有多个输入箭头和一个输出箭头的菱形。不需要条件,见图13-122。
菱形也用于分支(与合并相反),但不会混淆。因为分支有一个输入箭头和多个输出箭头,并且都有监护条件。
可以结合分支与合并,但用处不大。它可以有多个输入和多个带标签的输出。
注意:合并只是一种便利的表示法,省略它不会丢失信息。合并和分支常常成对使用。图13-122 合并
讨论
请区分合并和结合,合并汇合了两个以上的控制路径。在任何执行中,每次只走一条,无需同步。
结合汇合了两条或以上的并行控制路径。在任何执行中,所有路径都要走过,当它们都到达结合的源状态时,结合才被激活。
202.消息(message)
从一个对象(或其他实例)到另一个对象传递消息,除非活动可以保证这一点。消息可以是信号或调用操作,收到消息实例被认为是收到事件的实例。
见调用(call)、合作(collaboration)、交互(interaction)、操作(operation)、发送(send)、信号(signal)。
语义
消息是从一个对象(发送者)向另一个或几个其他对象(接收者)发送信号,或由一个对象(发送者或调用者)调用另一个对象(接收者)的操作。消息的实现有不同方式,如过程调用、活动线程间的内部通讯、事件的发生等。在逻辑层次上,发送信号和调用操作是类似的,都激活发送者和接收者之间的通讯,接收者收到一个值,并由此判断应该干什么。调用可以视为一种信号,激活一个发送,显式带有一个指针变元,随后返回的信号由它带回返回值。在实现层次上,信号和调用各有不同的属性和行为,因此是不同的UML元素。
收到信号可能引起接收者状态机的转换。接收者有两种不同的调用处理方式可以选用(由接收者的模型决定方式)。操作作为过程体(方法)实现,当信号到来时它将被激活。过程执行完后,调用者收回控制权,并可以收回返回值。另一种方式是主动对象,操作调用可能导致调用事件,它触发一个状态机转换。这种情况下,没有方法体,但转换可以有动作,转换也可为调用者提供一个返回值。转换完成后或调用事件未触发转换时,调用者收回控制。
消息中带有目标对象表达式的集合。消息发往集合中的所有对象。除非另行说明(有约束),消息将并行地送往所有对象。这说明执行的顺序是不定的,可以是并列的。如果必须按照一定顺序发消息,它们应该循环发送。对于调用,所有调用完成后,调用者收回控制。
发送消息的时间可以用列在消息名字上的表达式表示。
见时间标志(timing mark)。
结构
消息有发送者、接收者和活动。
在交互中,发送者是发出消息的类元角色。接收者是接收到消息的类元角色。活动为调用、信号、发送者的局部操作或原始活动,如创建或销毁。活动带有参数表、接收者列表、以及指向激活的操作或信号的指针。还可以有消息执行的条件或迭代说明。
在交互中,消息之间有前驱-后继关系和调用-被调用的关系,后者适用于过程方法。每次调用增加一个嵌套层次。在调用中,消息是有序的,可以并行。
前驱-后继(顺序)关系将线程上的消息组织为一列。一个消息可以有多个前驱或者后继。如果两个消息之间没有顺序关系并且没有共同的前驱,它们就可以并行。如果一个消息有多个前驱,只有在所有前驱完成后,该消息才能执行。这种消息是一个同步点。
调用-被调用(激活)关系定义了嵌套的过程结构。调用过程(使用调用事件)的消息是被调用者的过程体内所有消息的激活者。其中,被调用消息也有前驱-后继关系,由此确定相对顺序(允许并行)。
如果消息为调用,在调用过程完成并返回之前,调用者将锁定。如果接收者将消息处理为调用事件,初始转换完成后就出现返回值,此后调用者收回控制,被调用过程继续执行。
顺序和激活关系只涉及同一个交互中的消息。
表示法
顺序图和合作图的表示法不同。
顺序图(Sequence diagram)
顺序图中,消息表示为从一个对象(发送者)的生命线指向另一个对象(目标)的生命线的实线箭头。与外部消息相比,如果箭头和生命线垂直,说明消息发送是即刻的,至少是很快的。如果箭头倾斜,则说明消息的传送有一定的时间延迟,其间可以传送其他消息。对象发给自身的消息,箭头的起点和终点都是同一条生命线。消息按时间顺序从顶到底垂直排列。如果多条消息并行,它们之间的顺序不重要。消息可以有序号,但因为顺序是用相对关系表示的,通常省略序号。
传递延迟 消息箭头通常是水平的,说明传递消息的时间很短,在此期间不会"发生"其他事件。对多数计算而言,这是正确的假设。如果消息的传送需要一定时间,在此期间可以出现其他事件(来自对方的消息到达),则消息箭头可以画为向下倾斜的。
分支 从同一点发出多个箭头表示分支,每个箭头有监护条件。根据条件是否互斥,有条件型和并列型两种结构。
重复 相连的一系列消息可以被封装并标为重复的,重复标志说明这组消息可以多次出现。对过程而言,重复执行的条件列在重复的下方。如果有并行,则可能有某些消息是重复的部分,有些只执行一次。
合作图(Collaboration diagrams)
在合作图中,消息表示为带有标签的箭头,附在连接发送者和接收者的路径上。路径用于访问目标对象,箭头沿路径指向接收者。如果消息发送给对象本身,箭头指向对象自己,并标有关键字《self》。一个连接上可以有多个消息,沿相同或不同的路径传递。顺序由序号表明。
双视图(Both diagrams)
消息箭头上标有消息名字(操作或信号名)以及参数值。消息上还可以有序号,表示它们在交互中的作用。顺序图中箭头的物理位置表明了相应的顺序,可以省略序号。合作图中必须有序号。序号可以表明并行线程,这对两种图都有用。消息还可以有监护条件。
控制流类型 下列不同的箭头形状表示不同的控制流。
实心实线箭头
过程调用或其他嵌套控制。外层序列从新开始之前,应该完成所有内层序列。可以用于常规过程调用。也可用于并行活动状态。表示其中一个状态发送了信号,并在等待嵌套行为序列完成。
棍状箭头
平面控制流,每个箭头表示下一个执行顺序。对于嵌套过程,它对应于搜索叶节点的向底扫描活动。
半个棍状箭头
异步控制流。与棍状箭头不同,用于表示两个对象之间按顺序执行的异步消息。
虚线棍状箭头
从过程调用返回,返回箭头可以忽略。因为它是隐含在活动
结束时的。
其他变体
可以表示其他控制种类,如"超时"、"中止"等。这些是UML核
心之外的扩展。
消息标签 语法如下:
标签说明发送的消息、参数和返回值,以及大型交互中消息的顺序,包括调用嵌套、分支、分支、并列和同步等。
前驱 合作中,前驱列出的序列号用逗号隔开,并后跟反斜线(/)。
序号列表/
如果列表为空,则省略该条目。
每个序号是一个无任何迭代项的顺序表达式,它必须与其他消息的序号相匹配。
这表示在列表中的所有序号代表的消息出现之后本消息才能发送(一个线程跨越所要求的消息流,监护条件仍然满足)。因此,监护条件表示线程同步。
注意:序号在某个消息之前的消息是它的默认前驱,不用特别列出。同一前缀的消息序号构成序列。数字前驱是指该序号最后一位少1,即消息3.1.4.5是 3.1.4.6的前驱。
顺序图中,可视的顺序决定序列。对象发送自身的任何消息之前出现发给自身的多个消息,表示同步。
序号表达式 序号表达式是顺序子句列表,之间用冒号(:)隔开。每个子句代表交互中一个嵌套层次。如果所有控制并行,则无嵌套。语法如下:
标签 循环opt
其中标签是整数或者名字
整数代表消息所在层次。例如消息3.1.4在活动3.1的消息3.1.3之后。
名字代表并发控制线程。例如:消息3.1a和3.1b在3.1中并行。所有并行控制线程在同一嵌套层次上深度相同。
循环代表条件或迭代执行。表示根据条件执行0个或多个消息。选择有:
*[迭代子句] 迭代
[条件子句] 分支
迭代代表了给定深度上的消息序列。[迭代子句]可以省略(未指定迭代条件)。[条件子句]用伪代码或程序设计语言实现。UML没有说明其形式。可以为:*[i:=1..n]。
条件表示一条消息的执行取决于条件子句是否成立。条件子句用伪码或程序设计语言实现。UML没有说明其形式,例如:[x>y].
注意:分支与迭代的表示法一样,只是没有*号。可以视为执行一次的迭代。
表示法假设其中的消息将顺序执行,也可能并行执行,用双竖线表示(*||)。
签名 是说明名字、属性、操作返回值、消息或信号的字符串。有下列属性:
返回值列表
说明交互中消息返回值的名字,名字之间用逗号隔开。它可以作为后续消息的参数。如果消息不返回值,则省略返回值和赋值操作。
消息名字
目标对象中引发的事件名字(通常是要求执行操作的事
件)。可以用不同的方式实现,其中之一是操作调用。若实现为过程调用,它就是操作名。操作必须在接收方的类中定义或继承。其他情况下,它可以是接收方引发的事件名字。通常用消息名字和参数表都来确定一个操作。
参数列表
括号中用逗号隔开的参数表。空表也可以使用括号。每个参数是使用伪代码或适当编程语言写出的表达式(UML中未说明)。表达式可以使用以前消息(同一作用域)的返回值和起源于同一对象的导航表达式(即其属性、发出的链接和可达路径)。
举例
下文为控制消息标签语法
2:display(x,y) 单个消息
1.3.1:p:=find(specs) 带返回值的嵌套调用
[x<0] 4:invert(x,color) 条件消息
3.1*:update() 迭代
A3,B4/C2:copy(a,b) 与其他线程同步
表示选项
在消息边上表示数据标记,可以代替参数和返回值的文本表达
(图13-123)。标记是标有参数或者返回值的小圆圈,其上的箭头指向消息的方向(参数)或反方向(返回
值)。标记代表了返回值和参数。文本和标记两种表示法都可以使用,但是文本方式更简练,建议使用。
消息语法由编程语言的语法说明,如C++或Smalltalk语言。但视图中的所有表达式应使用同一种语法。
203.元类(metaclass)
这种类的实例是类,通常用于构造元模型。元类可以用关键字《metaclass》建模为一个类的构造类型。
见强类型(powertype)。
204.元-元模型(meta-metamodel)
定义了表达元模型使用的语言的模型。元-元模型与元模型之间的关系类似于元模型与模型之间的关系。这一层次通常仅仅与工具建造者、数据库建立者有关。UML就是一种称为元对象机制(Meta-Object-Facility,简称MOF)的元-元模型定义的。
205.元模型(metamodel)
定义表达模型所用语言的模型,是元-元模型的实例。UML元模型定义了UML模型的结构。
206.元对象(metaobject)
元模型语言中所有实体的统称,例如:元类、元类型、元属性、元关联。
207.元关系(metarelationship)
关系描述符及其实例关系的统称,包括实例关系和强类型关系。
208.方法
操作的实现,说明生成操作结果的算法或过程。
见具体(concrete)、操作(operation)、关系(realization)
语义
方法是操作的实现。如果操作不是抽象的,它就必须有方法或调用事件,或定义在具有操作的类上,或从组类继承。方法用过程表达式说明,是特定语言书写的字符串(如C++、SmallTalk或自然语言),用来说明算法。语言应与目的相适应。例如:自然语言适于早期分析,不适用于生成代码。
除非操作声明为抽象的,否则操作声明隐含方法的存在。泛化继承中,每次迭代声明的方法重载了同一操作中的任何继承方法。
注意,方法是可执行的过程--一种算法--而不是结果说明。例如,事前-事后说明不是方法。方法受制于算法、计算复杂性和封装的实现和地址分配问题。
在某些方面,方法的属性会比其操作更严格。操作没有定义为查询,但方法可以声明为查询。如果操作定义为查询,则方法必须是查询。同样的,方法可以强化并行属性。顺序操作可以被实现为条件控制或者并行的方法。此时,方法符合操作的声明,只是加强了其中的约束。
表示法
方法用操作声明表示,只是没有抽象特征(图13-124)。如果操作是继承的,迭代操作的声明的一般形式(非书写体)表示法,给出具体操作。方法体的文字表示为注释,连到操作表项。图中通常不表示法体,它们对文本编辑器是隐藏的,可用命令行方式呈现。
209.模型(model)
系统语义的完整抽象。
见包(package)、子系统(subsystem)。
语义
模型是从一个特定视点对系统进行的或多或少的完整抽象。说它是完整的,因为它从给定视图全面地描述了系统或实体。提供独立视图的模型可以独立维护。
模型可以分解为包的层次结构。最外层的包对应于整个系统。模型的内容是从顶层包到模型元素的包含(所有)关系的闭包。
模型还可能包含一部分系统环境,表示为行为者和界面。特别可以建立环境与系统元素的对应关系。系统及其环境构成了更高层次上的系统。
不同模型中的元素彼此没有直接影响。但它们可能代表了同一概念的不同层次、细节或开发步骤。因此,它们之间的关系,如跟踪或细化,对开发过程十分重要,往往会影响重要的设计决定。
表示法
模型可以表示为包,并带有构造类型《model》。但表示法中没有什么细节来表示模型。工具可以表示模型列表,但是其间很少有关系。最有用的是将模型名字变为其顶层包的名字,或者其中所有内容的映射。
讨论
没有一种系统视图或系统本身可以称为完全的,因为系统总能与外界有某种模型中没有表示的联系。因此,封装模型是一个相对的概念,必须指定实际工作的需求。
UML模型是一种包,它着重于某个视图。每个模型有自己的层次,可以与系统其他视图的层次相同或不同。
210.模型元素(model element)
从建模的系统中抽象出来的元素。与表达元素不同,表达元素(通常可视)是一个或几个与人交互的模型元素。
语义
所有有语义的元素都是模型元素,包括现实世界的概念和计算机系统中的概念。表现模型为目的的图形元素是表达元素,不是模型元素,因为其中不含有语义信息。
模型元素可以有名字,不同类型元素的名字的使用和限制不同,下面将分别说明。每个模型元素有与其类型的相符的命名空间。所有模型元素可以有下列属性。
标签值
任何模型元素或表达元素可以带有0个或多个标签-值对。标签是说明值的含义的名字。标签在UML中不是固定的,但可以扩展,从而表示各种建模者或编程工具有用的信息。
约束
模型元素可以有0个或多个约束。约束是用约束语言语言串表达的限制条件。
构造类型
模型元素可以与0个或多个构造类型名字相关,只要构造类型应用于基模型元素。构造类型不改变基类结构,但是可以为有该构造类型的元素增加标签
此外模型元素可以参与依赖关系。
见第14 章标准元素(Standard Elements),预定义的标签表(a list of predefined tags)、约束(constraints)、构造类型(sterotypes)。
211.模型管理视图(model management view)
模型的这一特征将自身组织为结构化的部分--包、子系统和模型。这种视图有时作为静态视图的一部分,通常与静态视图类图组成使用。
212.建模时间(modeling time)
出现于软件开发过程中建模活动中,包括分析和设计。使用注意:讨论对象系统时,区分建模时间与运行时间是非常重要的。
见开发过程(development process)、建模步骤(stages of modeling)。
213.模块(module)
存储和操作用的软件单元,包括源代码模块、二进制代码模块和可执行代码模块。它不与个别UML结构相对应,而是包含几个结构。
214.多对象(multiobject)
指明多个对象集合而非单对象的类元角色。
见类元角色(classifier role)、合作(collaboration)、消息(message)。
语义
多对象是代表多个对象的类元角色,多个对象通常在关联的"许多"端。多对象在合作中使用,表示以一对象集而非单对象为单元的操作。例如:在对象集中查找一个对象的操作作用于整个集合而非个别对象。这种分组不影响系统基本的静态模型。
表示法
多对象用两个矩形表示,上面的矩形偏向斜下方,表示有许多矩形(图13-125)。指向多对象的符号的消息箭头表示送往这些对象的消息。例如:查找一个对象的选择操作。
要对相关对象集中每个对象执行操作,要有两个消息:一个迭代消息生成指向个个对象的路径,另一个消息通过这些路径(暂时)发送消息。图示中可简化为,消息合并为一,包括一个迭代和对每个对象的应用。目标角色名的描述为"许多"(*),表示有多个隐含的连接。虽然可将它写为单个消息,但它在基本模型中(及在任何实际代码中),需要两层结构(操作连接迭代,使用连接消息)。
来自集合的对象表示为常规的对象符号,并用组成链与多对象相连,表示它属于集合。指向单个对象符号的箭头表示发给单个对象的消息。
典型地,发给多重对象的选择消息返回指向某一对象的指针,随后原发送者再向它发送消息。
215.多重类元(multiple classification)
泛化的一种语义变体,其中一个对象可以直接属于多个类。
语义
它是一种语义变体,其中对象可以是多个类的直接实例。与动态类元共同使用时,对象可以在运行时获得/失去类。它允许类代表对象承担的临时角色。
虽然多重类元符合常见的逻辑关系,但却给编程实现造成了困难,常用的语言不支持多重类元。
|