UML参考手册
第三部分 参 考 资 料
第13章 术 语 大 全
94.复制(copy)
交互中使用的一种流关系,目标对象成为源对象的一个副本,随后二者相互独立。
见变成(become)。
语义
复制关系是一种流关系,它表示在交互中一个对象派生出另一个对象。它代表了制作副本的活动。复制流执行过后,两个独立对象的值可以独立的变化。
交互中的复制转换可以带有序号,表示它与其他活动相关的发生。
表示法
复制流是用从原始对象指向新生成对象的虚线箭头表示的。箭头上标有构造型关键字《copy》,还可以有序列号。复制转换可以出现于合作图,顺序图和活动图中。
举例
图13-83表示一个文件在另一个节点上制作备份。首先进行复制(《copy》),随后将副本移动到下一个节点(《become》)位置。
图13-83 复制和become流95.创建(creation)
对象或其他实例(如用例实例)的实现和初始化。反义词:销毁。
见实例化(instantiation)。
语义
创建对象是实例化对象消息的结果。创建操作可以有参数,它们将用于新生实例的初始化。创建操作后,新的对象遵从其类的约束,并可以接收消息。
创建操作或者构造函数可以被声明为类作用域的操作。此类操作的目标(至少在概验上)是类本身。程序设计语言如Smalltalk中,类和运行时的对象一样的实现,因此创建操作和类的常规消息一样实现。在C++中,没有实际的运行时对象,创建操作可以被视为运行时被优化的概念化消息。C++的方法中排除了实例化类的计算。否则,
每一个方法都可被建模为传递给类的消息。
类属性的初始值表达式(在概念上)是由创建操作计算的,其结果用于属性的初始化。创建操作的代码可以隐式取代这些值,因此初始值表达式是可重载的默认项。
在状态机中,创建对象的构造操作的参数作为离开顶层初始状态的转换上默认的事件使用。
表示法
在类图中,创建操作(构造函数)做为一个操作包含在类的操作表中。它可以有参数表,返回值是类的实例,可以省略。作为类作用域的操作,其名字带有下划线(图13-84)。表示《constructor》构造型。
图13-84 创建操作
顺序图中的创建操作的执行用消息箭头表示,箭头指向对象符号(带有下划线对象名的矩形)。对象符号下发是对象的生命线。(根据对象是否活动,可以为虚线或者双实线)。它持续到对象被销毁或者图结束(图13-85)。
图13-85 创建顺序图
图13-86 合作图中的创建
合作图中创建操作的执行用在带有特性{new}的对象符号表示。传递给本对象实例的第一条消息隐式为创建对象的消息。虽然消息实际指向类的本身,但通常被省略。消息用于实例(新生但未初始化)的初始化。如图13-86所示。
见 合作图(collaboration diagram),顺序图(sequence diagram),那里有过程实现中创建的表示法。
96.当前事件(current event)
在状态机的执行中触发运行至完成步骤的事件。
见运行至完成(run to completion)、状态机(state machine)、转换(transition)
语义
为了方便起见,状态机可以把几个相连的转换信号变成一个事件的响应。除了最终转换外的所有转换都进入伪状态--为了构造状态机而存在的哑状态,它不等待外部事件。原则上,所有的消息可以汇集到一个转换上,但是,用伪状态划分多状态可以使多个转换共享普通后继事件。
转换链的执行是原子的--即,是不能被外部事件打断的运行至完成步骤的一部分。在这样的一列转换的执行中,消息附属的活动和监护条件有通向触发的第一个转换的事件及其参数的隐含入口。这个事件就是转换中的当前事件。当前事件的类型可以被多态操作或者条件语句识别。一旦知道了确切的类型,就可以访问其参数了。
当前事件特别有利于帮助新创建对象的初始转换得到初始化参数。新对象创建后,创建事件成为当前事件,其参数可以被新对象状态机的初始转换所使用。
举例
图13-87 是从idle状态到Purchase状态的转换,它由Request事件触发。Purchase的入口活动调用setup操作,它使用当前事件。程序可以访问当前事件,从而得到Request事件及其参数producct。如果有当前事件多个绑定,程序需要一个条件语句来得到正确的触发事件。语法由程序设计语言说明。
表示法
当前事件的命名,可以在带有关键字currentEvent的表达式中完成。特定的表达语言提供更详细语法。
图13-87当前事件的使用
97.数据类型(data type)
没有标识符的一组值的描述福(独立存在,可能有副作用)。数据类型包括原始预定义的类型和用户自定义的类型。原始类型右:数字、字符串、乘方。用户定义的类型是枚举类型。程序语言中用于实现的匿名数据类型可以用语言类型定义。
见类元(classifier)、标识符(identity)。
语义
数据类型是用户可定义类型所需的预定义的基础。它们的语义是在语言结构之外用数学定义的。数字是预定义的,包括实数和整数。字符串也是预定义的。这些类型使用户不可定义的。
枚举类型是用户自定义的一组命名元素,它们之间有预定义的顺序,此外没有其他属性。枚举类型有名字和一系列枚举值。预定义了枚举类型Boolean,其枚举值为false和true。
操作可以在数据类型上定义,操作的参数可以有数据类型。因为数据类型没有标识符,只是简单值,数据类型上的操作不对数据类型进行修改;它们直接返回值。因为没有标识符,创建新的数据类型是没有意义的。所有数据类型的值(概念上)是预定义的。数据类型上的操作是对系统的一种请求,它不改变系统状态,仅返回一个值。
数据类型还可以用语言类型定义--程序设计语言中的数据类型表达式。此类表达式用目标语言指定了一个命名的数据类型。例如表达式person*(*)(string)是C++中的一个数据类型表达式,它不是简单的数据类型了。
98.数据值(data value)
是数据类型的实例,是不带标识符的值。
见数据类型(data type)、对象(object)。
语义
数据只是一个数学域的号码--一个纯数值。因为数据值没有标识符,两个表示法相同的数据值是无法区分的。在程序设计语言中,数据值使用值传递。用引用传递数据值是没有意义的,变换数据值也是没有意义的,它的值是永远不变的。实际上,数据值就是值本身。通常所说的变换数据值,是指变换一个有数据值的变量的内容,使其带有新的数据值。而数据值本身是不变的。
99.默认值(default value)
作为某些程序设计语言或者工具的一部分而自动提供的值。元素属性的默认值不是UML语义的组成部分,在模型中不出现。
100.延迟事件(deferred event)
当对象处于特定状态时,一个被认证时间被延迟的事件。
见状态机(state machine)、转换(transition)。
语义
一个状态可以将一系列事件指定为延迟的。对象处于使某个事件延迟的状态时,如果该事件发生,则它将不会触发相应转换,即事件没有及时效应。直到对象转入一个不要求该事件延迟的状态之后,事件才有效用。在该状态活动时出现其他事件按照常规处理。对象进入新的状态之后,不再被延迟的保存事件一一出现,并在新的状态下触发转换(先前被延迟的事件的出现顺序是不定的,依赖事件的特定出现次序是危险的)。如果事件在新的状态下没有触发转换,则它将被忽略并丢失。
在常规状态机中,应小心的使用延迟事件。它们可以更直接的被构造为并行状态相应的事件,在此期间,主运算部分可以进行其他工作。在活动图中使用,可以保证运算顺序进行,并且不会丢失异步性信息。
如果状态中有被延迟事件触发的转换,该转换将重载延迟。
表示法
延迟事件表示为带有特殊保留动作延迟的内部转换。延迟用用于状态及其嵌套子状态。(图13-88)
101.委派(delegation)
一个对象对于另一个对象所发的信息的回应能力。授权可以用作继承的选项。在某些语言(如self)中,它由语言的继承结构支持。在大多数其他语言中(如C++和Smalltalk),它可以通过与另一个对象的聚集或者关联实现。第一个对象的操作要求第二个对象的操作继续完成它的工作。对比:继承。
见关联(association)。
图13-88延迟事件102.依赖(dependency)
两个元素之间的一种关系,其中一个元素(服务者)的变化将影响另一个元素(客户),或向它(客户) 提供所需信息。它是一种组成不同模型关系的简便方法。
语义
依赖关系是表示一个或几个模型中两个元素间关系的语句。它可以将几种不同的元素结合起来。好像生物学中用"无脊椎动物"结合所有不是"脊椎动物"的不同门的生物。
表现不对称的知识系统时,独立的元素成为服务者,不独立的元素成为客户。
为了说明依赖关系在模型中的角色,它可以带有名字。但是依赖关系自身的表示通常足以说明问题,不需另加名字。依赖关系可以有构造类型,用来建立依赖关系的精确属性。依赖关系还可以有文字说明,用来对它进行详细描述。
两个包之间有依赖关系,说明两个包中至少一对元素之间有依赖关系。例如,两个类的使用之间的依赖关系可以表示为两个包含它们的包之间的依赖关系。两个包之间有依赖关系不能说明两个包中所有的元素有依赖关系--事实上,这种情况非常少见。
见包(package)。
依赖关系中可以包含下属依赖关系的引用。例如,两个包之间的依赖关系可以引用两个类之间的依赖关系。
依赖关系不必传递。
注意,关联和泛化关系满足依赖关系的一般定义,但是它们有各自的模型表示法和含义,通常不被视为依赖关系。实现关系有独立的表示法,但是被视为依赖关系。
有几种不同的依赖关系:抽象(abstraction)、绑定(binding)、组合(combination)、许
可(permission)、使用(usage)
抽象(abstraction).抽象依赖关系代表不同的抽象层次。两个元素用不同的方发表示同一个概念。通常一个元素更抽象,另一个更实际;也可能两个元素是同一抽象层次的不同表示法。从不具体到具体的顺序,抽象包括构造类型、描述、精化(关键字refine)、实现(由独立的表示发)、派生(关键字derive)。
绑定(binding). 绑定依赖关系将由模板约束的元素域模板相连。模板参数的要求作为绑定附属的列表。
许可(permission).许可依赖(通常作为特定的构造类型)将包或者类与另一个允许它使用某些内容的包或者类相连。许可依赖关系的构造类型有访问、友元、输入。
使用(usage).使用依赖关系(关键字《use》)将客户元素与服务者元素相连。服务者的变化将导致客户的变化。使用通常表示一种实现的依赖关系,其中的一个元素依靠另一个元素的服务来实现自身的操作。使用的构造类型包括调用、实例(关键字《instantiate》)、参数、发送。这是一个开放的列表,不同的程序设计语言中有其他的使用依赖关系。
表示法
依赖关系用两个模型元素之间的虚线箭头表示。箭尾处的模型元素(客户)依赖于箭头处的模型元素(服务者)。箭头上可带有表示依赖关系种类的关键字,还可以有名字(图13-89)。
图13-89 类之间的一些依赖关系
有几种其他的关系也使用有关键字的虚线箭头表示,但它们不是依赖关系。这些元素有流(成为和复制)、组合(扩展和包含)、约束和注释。如果注释或者约束是元素之一,可以省略箭头,因为约束或者注释总是在箭尾处。
标准元素
成为(become)、绑定(bind)、调用(call)、复制(copy)、创建(create)、派生(derive)、扩展(extend)、包含(include)、导入(import)、友元(friend)、~的实例(instanceOf)、实例化(instantiate)、强类型(powertype)、发送(send)、跟踪(trace)、使用(use)。
103.配置(deployment)
描述现实世界环境运行系统的配置的开发步骤。在这一步骤中,必须决定配置参数、实现、资源配置、分布性和并行性。这一步骤的结果体现于扩展图和结构文件中。
见开发过程(development process)、建模步骤(stages of modeling)
104.部署图(deployment diagram)
表示运行时过程节点结构、构件实例及其对象结构的视图。构件代表代码单元在运行时的表现。不作为运行时内容的构件不出现在部署图中,而是在构件图中表示。部署图表现实例;构件图表现构件类型的定义。
见构件(component)、接口(interface)、节点(node)。
语义
部署图含有用通信链相连的节点实例。节点实例包括运行时的实例,如构件实例和对象。构件实例和对象还可以包含对象。模型可以表示实例及其接口之间的依赖关系,还可以表现节点或者其他容器之间实体的移动。
部署图有描述符形式和实例形式。实例形式(前文已经介绍过)表现了作为系统结构的一部分的具体节点上的具体构件实例的位置。这是部署图的常见形式。描述符形式说明哪种构件可以存在于哪种节点上,哪些节点可以被连结,类似于类图。
表示法
图13-90客户-服务器系统的部署图
部署图是节点符号与表示通讯的路径构成的网状图。(图13-90)。节点符号可以带有构件实例,说明构件存在或运行于该节点上。构件符号可以带有对象,说明对象是构件的一部分。构件之间用虚线箭头相连(可能穿过接口),说明一个构件使用了另一个构件的服务。必要时可以用构造类型说明依赖关系。
部署图类似于对象图,通常用于表示系统中的各个节点的实例。很少用部署图定义节点的种类和节点之间的关系。
构件在节点之间的移动和对象在构件之间的移动可以用带有关键字《become》的虚线箭头表示。在这种情况下,构件或对象只在一部分时间内处于相应节点或者构件上。图13-133的部署图中的对象在节点之间移动。
见成为(become)
105.配置视图(deployment view)
表示分布式系统中的节点,在各个节点上的构件以及节点上的构件中的对象的视图。
见配置(deployment)、部署图(deployment diagram)。
106.派生(derivation)
两个元素间的一种关系,可从一个元素计算出另一个元素。派生可建模成一个带有关键字derive的抽象依赖的构造型。
见导出元素(derived element)。
107.导出元素(derived element)
可以由其他元素计算得出的元素,它不增加语义信息,只是为系统设计的方便而存在。
见约束(constraint)、依赖(dependency)。
语义
模型中的导出元素在逻辑上讲是多余的,因为它可以由一个或者几个其他元素计算得出。计算导出元素的公式可以作为约束给出。
模型中使用导出元素有几种原因。从分析层次上看,导出元素不是必须的。但是它可以作为一种宏来定义或者命名一个有用的概念。必须记住,导出元素没有为模型增加语义信息。
在设计层次的模型中,导出元素代表一种选择--模型中使用导出元素避免了重复计算的开销。例如计算的中间结果或者对一列值的引用。使用导出元素,隐含的要求导出元素所依赖的元素变化后,导出元素随之刷新。
图13-91 派生属性和派生关联
表示法
在元素名字之前加上斜线(/)表示导出元素。例如属性,角色名或者关联名(图13-91)。
计算导出元素的具体方法可以用带有构造类型《derive》的依赖关系说明。通常,将依赖关系的箭头从元素的约束箭头中去掉,并在导出元素的边上加一条约束字符。
讨论
派生关联可能是最常见的导出元素。它提供了一种可以由两个或者两个以上的基础关联计算出来的虚拟关联。派生的关联为WorksForCompany,可以由WorksForDepartment和employer组合计算得出。在实例中使用WorksForCompany可以避免重复进行计算,但是这一关联不提供任何额外信息。
关联泛化(图13-30)略有不同。它提供了针对同一个关联的两个不同层次的细节内容。通常不会同时实现两个层次,而是只实现子关联。有时也会实现父关联,并将子关联作为约束。
108.后代(descendant)
是指一个子或者含有一个子关系链的元素,是特定关系的传递闭包。反义词:祖先。
109.描述符(descriptor)
用来描述一系列实例的共有属性的模型元素。属性包括结构、关系、行为、约束、目的等等。 对比:实例。
语义
描述符是描述一列实例的模型元素。模型中的大多数元素都是描述符。这个词几乎包含了模型的所有内容--类、关联、状态、用例、合作等。有时"类型(type)"表示相同的含义。但是通常"类型"的适用范围比较窄,仅仅指类似于类的元素。描述符包括所有其解说作用的元素。它有内涵和外延。内涵是结构描述和常规规则;外延是描述符所解说的实例。外延在运行时不一定是物理上可以访问的。模型中的一对重要关系就是描述符--实例。
表示法
表示描述符和实例之间的关系,使用相同的集合符号表示二者,同时在实例的名字下方画一条线。描述符有名字;实例既有自身的名字又有描述符名字,二者用冒号隔开,名字带有下划线。
110.设计(design)
系统的一个阶段,它从逻辑层次说明系统将如何实现。在设计中,从战略和战术上确定如何满足功能需求和质量要求。者一步的成果体现为设计层模型,特别是静态视图,状态机图和交互视图。 对比:分析、设计、实现、扩展。
见建模步骤(stages of modeling)、开发过程(development process)。
111.设计时间(design time)
是指在软件开发过程的设计活动中出现的(情况)。对比:分析时间。
见建模时间(modeling time)、建模步骤(stages of modeling)
112.销毁(destroy)
消灭一个对象并收回其资源。它通常是一个明确的活动,也可以是其他活动,约束或废物回收的结果。
见销毁(destruction)
113.销毁(destruction)
消灭一个对象并收回其资源。消除一个组成对象将导致消除其组成部分。消除一个对象,不会消除与它由一般关联或者聚集关系的对象,但是包含该对象的链接将被消除。
见组成(composition)、终态(final state)、实例化(instantiation)。
表示法
在过程实现中的销毁的表示法,见合作图和顺序图(图13-162)。在顺序图中,在对
图13-92 创建和销毁
象的生命线上画大×表示对象被销毁(图13-92)。它的位置是在导致对象被销毁的信息上,或者在对象自我终结的地方。销毁对象的信息可以带有构造类型《destroy》。在合作图中,用对象上的约束{destroyed}表示对象在交互中被销毁。如果对象在交互中生成并被销毁,可以使用约束{transient}。
114.开发过程(development process)
为了以一种受控制、可重用的方式生产软件而进行的一系列并行的有序工作,以及相关指导。软件开发过程的目的是为了保证完成的系统所需的功能和系统可靠性。
见建模步骤(stages of modeling)
讨论
UML是一种建模语言,而不是过程。它的目的是描述模型,而该模型可以用不同的开发过程实现。为了标准化,描述开发工作的结果比解释开发过程更为重要。因为有很多很好的建模方法,而且模型的最终使用者也不必了解它的构造过程。因此UML支持多种过程。
关于交互的详细信息、用例触发、技术过程,见[Jacobson-99]。
建模步骤与开发阶段的关系
建模步骤适于迭代的开发过程,包括初始、细化、构造和转换四个阶段。在一个应用程序的开发中,这些过程顺序进行,但每个步骤包含一次或者多次迭代。在一次迭代中,每个模型元素按照从分析到配置的步骤行进。每个元素有相应的步速。虽然开发阶段和建模步骤不是同步的,但是二者之间有关联。在早期的开发阶段和每个阶段的早期迭代中,更强调早期建模步骤。
图13-93开发阶段后的进展
图13-93表示了在后继步骤和迭代过程中的着重程度的对比。在初期,主要着重于分析;在加工中建立面向设计和实现的元素过程模型;在构造和转变中完成所有元素。
115.图(diagram)
模型元素集的图形表示。通常为弧(关联)和顶点(其他模型元素)相互连接构成的。UML支持类图、对象图、用例图、顺序图、合作图、状态图、活动图、构件图和扩展图。
见背景信息(background information)、字体使用(font usage)、超级链接(hyperlink)、关键字(keyword)、标签(label)、包(package)、路径(path)、表示元素(presentation element)、特征表(property list)。
语义
图不是语义元素,而是表示有语义的模型元素。元素的意义不受表示法的影响。
图包含在包中。
表示法
多数UML的图和复杂符号是由路径连结的图形构成的。信息用拓扑结构表示,而不依赖于符号的大小、位置(有一些例外,如带有时间轴的顺序图)。有三种重要的可视关系:连结(通常是二维图形);容器(包含二维符号的闭合图形);可视的附件(图中"靠近"另一个图符的图符)。它们是语言的表示法中节点和连结的映射。
UML图画在二维表面上。有些内容是二维图形的三维投影,如管道。但是它们仍然被视为二维图符。将来三维布图可能会运用在桌面电脑上,但是目前仍然没有普及。
UML表示法中有4种图的结构:图表、二维图形、路径、字符串。
图标是大小,形状都固定的图形。它不能扩展也不含有内容。图标可以出现在其他图符中、作为路径的端点、或者作为独立图符。例如聚集的符号(菱形)、导航性(箭头)、终态(牛眼)、对象销毁(大X)都是图标。
二维符号有不同的大小,可以扩展并含有其他内容(如字符串或者其他符号)。其中许多多带有大小相同或者不同的分格。结束于符号边界的路径表示与二维符号相连的路径。例如,类的符号(矩形)、状态(圆角矩形)、注释(带折角的矩形)。
路径是一列线,或者终点相连的弯曲符号。在概念上,路径是一个单一的拓扑实体,但是它可以有多个表示消息的符号。消息不能脱离路径而存在。路径的两端多有其他图形符号(不能有悬空端)。路径可以有终点--在路径末端顺序排列的,对路径起限制作用的图标。例如关联的符号(实线)、泛化的符号(带有三角形图标的实线)、依赖的符号(虚线)都是路径。
字符串以一种"未经分析"的形式表示不同的信息。UML假定字符串的每个用例都可以通过相应的语法分析成为模型信息。例如属性、操作和转换都有各自的语法。这些语法可以被工具识别。字符串可以是分格的内容,是列表中的元素(列表中的位置传达信息时),是符号或者路径的标签,或者图中的独立元素。例如类名、转换标签、多重性的表示和约束都是字符串。
116.直接类(direct class)
最完整的解说一个对象的类。
见类(class)、泛化(generalzation)、继承(inheritance)、复重类元(multiple
classification)、多重继承(multiple inheritance)。
语义
一个对象可以是多个类的实例--如果它是某个类的实例,它就同时是该类的祖先的实例。直接类是对对象最完整最详细的解说。对象是直接类的直接实例,是直接类的祖先的间接实例。对象不能使其直接类的后代的实例(根据定义)。
如果系统允许多重类元,就不存在完整的描述对象的直接类。对象可以是多个类的联合直接实例。只要这些类的子类不描述同一个对象,对象就是所有包含其描述的类的直接实例。对象的直接列之间不能有祖先关系。
如果类的实例中生成了对象,该对象就是此类的直接实例。
117.直接实例(direct instance)
直接实例是一个由给定的类进行最详细描述的实例(如对象)。表述为"对象O是类C的直接实例"。这里C是O的直接类。
见直接类(direct class)。
118.判别式(discriminator)
从处于泛化关系中的一组子中选出一个子的伪属性。所有的子表示了使双亲特化的一个给定性质,对应于其他使双亲特化的隐含性质。它代表了一个特化的维度。
见 泛化(generalization)、强类型(powertype)、伪属性(pseudoattribute)。
语义
有时,模型元素可以基于不同的性质来特化。每个性质表示了一个特化的独立正交维度。例如交通工具可以按照动力进行特化(汽油发动机、火箭引擎、风力、畜力、人力),也可以按照适用范围进行特化(陆地、水中、空中、外太空)。说明者是一个说明维度的名字。一个对象可以从多个维度特化,但是它们必须表现为具体实例。
泛化关系可以有一个判别式,它是一个表示用于划分某个双亲的孩子的维度的字符串。用同一个判别式名对一个双亲进行特化而得到的所有特化关系构成了一个组,每个组是一个独立的特化维度。判别式名的完全集表示了特化双亲的维度完全集。实例必须同时是来至于每个特化组的子类的实例。例如,交通工具必须既有动力又有管辖地。
每个判别式表示了双亲的一个抽象性质,该性质通过具有与双亲有特化关系的孩子来特化。有多个判别式的双亲有多个维度,所有的维度都必须特为具体元素。因此处于一个判别式组中的孩子是抽象的。它们中的每一个只是双亲的部分描述,着重于某个性质而忽视其他。例如着重于动力的交通工具的子类忽略管辖范围。具体元素要求同时对所有的维进行特化。可通过对来至于每个维的孩子的具体元素的多重继承实现,或通过对来至每个维的孩子的实例的多重类元实现。在组成所有判别式之前,描述仍是抽象的。
例如实际的交通工具必须同时有动力和管辖范围。以风为动力的水上交通工具是帆船;畜力的空中交通工具没有名字,但是这种实例存在于童话中。
缺省判别式标识表示"空"判别式,"空"判别式仍被认为是合法的("默认" 判别式)。这一约定使得常见的无判别式的情况也可以同样处理。如果所有的泛化路径都没有判别式,则所有的子都处于同一判别式;换言之,所有特化都属于一个判别式,这与没有判别式的情况产生相同的语义。
结构
每个特化(泛化)弧都带有判别式字符串,它可以为空串。
判别式是其父的伪属性,它在其父的属性和关联角色中必须是唯一的。伪属性的域是子类集。在不同的孩子和双亲中允许多次出现同一个判别式名,表示这些孩子属于同一个部分。
表示法
判别式可表示为泛化箭头上的文本标签(图13-94)。如果带有同一判别式的两个泛化弧共用一个箭头,则判别式可以标在箭头上。
举例
图13-94表示了在两个维度上对Employee的一次特化:雇员的status和locality。每个维度都有由子类表示的值的范围。但产生的可实例化子类应该在两个维度上都满足。例如,Liaison类Supervisor和Expatriate。
在多重继承的子类中两个维度结合之前,单一维度的后代是抽象的。
图13-94 判别式119.互斥子状态(disjoint substate)
一个不能和同一组成状态中的其他子状态同时存在的子状态。对比:并发子状态。
见 复杂转换(complex transition)、复合状态(composite state)
120.分布单元(distribution unit)
定位于一个操作系统进程或者处理器中成组存在的一些对象或构件,可以表现为运行时的组成或者聚集。它是配置视图中的一个设计概念。
121.动态类元(dynamic classification)
一种泛化的语义变量,其中的对象可以变换类型或者角色。
对比:静态类元。
见多重类元(multiple classification)
语义
在许多程序设计语言中,对象实例化以后不能改变生成它的类。这种静态类元限制简化了编译器的实现,但是在逻辑上却不是必要的。例如,在静态类元下作为圆的实现的对象只能是圆,而不能在x轴上拉伸。在动态类元下,它可以在一个轴上拉伸成为椭圆。
UML模型中可以使用两种类元。尽管区别对于执行是很重要的,不同的选择对模型的影响很小。同一个类必须以两种方式定义,但其支持的操作在两种情况下可以不同。
动态并发性(dynamic concurrency)
一种代表多个并发执行的活动状态。
见活动图(activity graph)。
122.动态视图(dynamic view)
处理模型元素在不同时刻的说明与实现,与静态视图中的静态结构有区别。动态视图是一个组成术语,它包括了用例视图、状态机图、活动视图以及交互视图。
123.细化(elaboration)
软件开发过程中的第二步,开始系统设计,开发并测试体系结构。在此期间,完成分析视图以及设计视图的体系结构部分。如果构造了可执行原型,则也完成部分实现视图。
见开发过程(development process)
124.元素(element)
组成模型的原子。本书所说的是可以用于UML模型的元素--即表达语义信息的模型元素以及用图形表示模型元素的表达元素。
见图(diagram)、模型元素(model element)
语义
元素的意义相当广泛,没有什么具体的语义。
所有元素可以带有下列特征:
125.标签值(tagged value)
任何元素可以有0个或者多个标签值。标签是说明数值意义的名字。UML中的标签不是固定的,它可以携带任何对建模者或工具有意义的信息。
标准元素
documentation
126.入口动作(entry action)
进入一个状态时执行的动作。
见出口活动(exit action)、运行至完成(run to completion)、状态机(state machine)、转换(transition)。
语义
一个状态可以选择带有入口动作。无论怎样进入该状态,在外部状态的活动或者转换之后,内部状态的活动进行之前,都会执行入口动作。入口动作不能以任何方式越过。无论是独立状态还是嵌套状态活动时,都要先执行入口动作。
执行顺序。如果一个带有活动的转换连结的两个状态分别有入口动作和出口动作,执行顺序为:执行源状态及其外部状态(不包括源状态和目标状态公用的外部状态)的出口活动,随后执行转换上的活动。最后从目标状态的外部状态开始(外层优先)一一执行入口活动,直到执行完目标状态的入口活动为止。图13-117的转换带有这样的活动。
表示法
入口活动按照内部转换的语法编码,带有虚拟事件名字entry(entry是保留字,不能用作实际事件的名字)。
entry/动作序列
每个状态有一个入口活动,该活动可以是一个序列,这样就不会失去一般性。
讨论
入口和出口活动在语义上不是必须的(入口活动可以从属于所有进入状态),但它们实现了状态的封装,从而使外部使用与内部结构分开。它们允许定义初始化和终态活动,而不必担心会被略过。对于异常尤其有用,因为它定义的活动即使出现异常时也会被执行。
入口活动有助于完成进入一个状态时必须完成的初始化工作。可以对带有积累信息的变量的状态进行初始化。例如支持用小键盘输入账号或者电话号码的用户界面,在进入之前要清除上次的号码。入口活动还用来给状态分派临时存储空间。
通常,出口活动与入口活动一起使用。入口活动分配资源,出口活动释放它们。即使出现外部转换,资源也会被释放。这是处理例外和用户错误的好办法。用户级的错误将触发高级转换,并跳过嵌套状态,但嵌套状态在失去控制之前还可以释放空间。
127.枚举(enumeration)
枚举是一种数据结构,它的实例构成了有名字的字面值。通常,同时声明枚举名和其字面值的名字。
见类元(classifier)、数据类型(data type)
语义
枚举是用户定义的数据类型,它包括名字和枚举字面名字的有序序列。每个字面名字是枚举范围内的一个值--是本数据类型的一个预定义的实例。例如RGB Color={red,green,blue}。布尔数据类型是预定义的枚举类型,其字面值为true和false。
表示法
枚举表示为一个矩形,上方的分格中,在枚举名字上标有关键字《enum》(图13-95)。第二个分格中是枚举字面值的列表。第三个分格(如果表示)是此类型上的操作。它们必须是可以查询的,因此不必再确切的声明了。
128.事件(event)
占用一定时间和空间的出现情况的说明。
见状态机(state machine)、转换(transition)、触发(trigger)
语义
图13-95 枚举的声明
在状态机中,一个事件的出现可以触发状态的转换。事件由参数表(可以为空)从事件的产生者向接收者传递信息。事件发生的时间是每个事件的隐含参数。其他参数在事件中定义。
事件的出现(实例)带有与各个事件参数对应的参量(实际值)。这些参量的值可以被事件触发的转换所带的动作引用。
有4种事件:
调用事件(call event)
接收到一个请求,从而激活某个操作。希望的结果是事件的接收者触发一个转换,从而执行相应操作。事件的参数是操作的指针、操作的参数和返回指针。转换完成后,调用者收回控制权。
交换事件(change event)
满足事件某个表达式中的布尔条件,没有参数。这种事件隐含了对于控制条件的连续测试。当条件从假变为真时,事件将发生。事件中,条件被满足的时间常常与其他事件的发生有关,所以通常不需要定时询问。
信号事件(signal event)
收到一个信号,它是对象之间进行通讯用的特定的有名字的实体。信号有明确的参数列表。它由一个对象明确的送给另一个或者一些对象。广播可以视为送给所有对象的信号。但是在实践中,二者的效果可能不同。发送者在发信号时明确了信号的变元,发给对象的信号可能触发它们的零个或者一个转换。信号是对象之间异步通信的手段。进行同步通信,需要使用两个异步信号,每个通信方向上一个。信号可以泛化,从父信号生成的子信号继承父信号的参数,还可以增加自己的参数。子信号满足其祖先要求的触发。
时间事件(time event)
满足一个时间表达式,进入某状态后经过一定的时间;或者到达某个绝对时间后发生事件。注意,无论是时间段还是绝对时间,都可以用现实的时钟或者虚拟的内部时钟(不同的对象有不同的内部时钟)来定义。
表示法
见不同对象的表示法。
标准元素
创建(create),销毁(destroy)
129.异常(exception)
基本执行机制中由失败行为引起的信号。
见复合状态(composite state)、信号(signal)。
语义
异常通常由对应于执行中失败的实现机制隐式产生。它可以被视为发送给主动对象或者过程活动的信号,导致异常执行。对象的状态机可以对异常采取相应的行动。这包括忽略当前进程、跳转到执行中的某处、执行某个操作而不变换状态、或者忽略事件。向高层状态转换的功能使异常处理灵活和强劲。
因为异常是信号,所以它带有参数表。参数值由发现错误的执行机构(如操作系统)设定。处理异常的操作可以读到这些参数。大多数语言中,处理异常的操作可以控制它或将它转发。
表示法
用构造类型《exception》来区别声明和异常。状态机中的事件名字不用标以构造型。
130.出口活动(exit action)
退出一个状态时执行的活动。
见入口活动(entry action)、运行至完成(run to completion)、状态机(state machine),转换(transition)
语义
状态可以选择带有出口活动。无论以什么方式退出该状态,在内部状态或者转换所附属的活动完成后,外部状态的活动开始前,都要执行出口活动。出口活动不能以 任何方式跳过。在状态失去控制前一定要被执行。
入口和出口活动在语义上不是必须的(入口活动可以从属于所有进入状态),但它们实现了状态的封装,从而使外部使用与内部结构分开。它们允许定义初始化和终态活动,而不必担心会被略过。对于异常尤其有用,因为它定义的活动既是再出现异常时也会被执行。
表示法
出口活动按照内部转换的语法编码,带有虚拟事件名字exit(exit是保留字,不能用作实际事件的名字)。
exit/活动序列
每个状态只有一个出口活动,该活动可以是一个序列,这样就不会失去一般性。
讨论
出口活动可以在推出状态时完成必要的清理活动。它的最大作用是释放状态执行过程中分配的临时存储区和其他资源。
通常,出口活动与入口活动一起使用。入口活动分配资源,出口活动释放它们。
即使异常发生,资源仍被释放。
131.示出(export)
在包的语境中,通过调整元素的可视性而使得它可以在它的命名空间之外被访问。与访问和导入不同,它们是使外部元素可以在包内被访问。
见访问(access)、导入(import)、可视性(visibility)
语义
包通过调整元素的可视性水平,允许其他包看到该元素,从而实现示出(对于要导入该元素的包是公共的,保护它自身的子)。
讨论
一个元素要看到另一个同一等级的元素必须满足两个条件。包含该元素的包应该将它设定为公共可见的。此外,引用目标元素的包必须能访问或者导入包含目标元素的包。两者都是必须的。
132.表达式(expression)
可以用给定语言翻译的编码语句。许多表达式在翻译后产生某个值,其他执行特定动作。例如表达式"(7+5*3)"计算出一个整数。
语义
表达式定义了一个语句,它可以被一些实例、值、或者语境中的操作所使用。表达式不修改它所进行计算的环境。表达式包含字符串和计算所用语言的名字。
表达式包含翻译所用语言的名字和表达式的字符串(按照设计语言的语法编码)。假定该语言可以被翻译。提供翻译器是建模工具的任务。所用语言可以是约束-说明型语言,如OCL;可以是程序设计语言,如C++,Smalltalk;或者是人类语言。当然,自然语言书写的表达式不能被工具自动计算,而必须有人来处理。
表达式的不同子类产生不同类型的值,有布尔表达式、对象集表达式、时间表达式、过程表达式。
UML模型中的表达式可以作为活动、约束、监护条件等等。
表示法
表达式是用指定语言表述的字符串。表达式的语法由工具或者语法分析器识别。认为分析器可以在运行时识别这些字符串并得到相应的值;或者识别语义结构从而了解表达式的意思。例如布尔表达式可以计算出true或false值。建模工具应该知道所使用的语言,图中一般不会标明。表达式本身通常已经表明了自身的意义。
举例
self.cost<authorization.maxCost
forall(k in tagret) {k.update()}
133.扩展(extend)
是指扩展用例与基用例之间的关系。特别是如何将扩展用例定义的行为插入基用例定义的行为序列。扩展用例以模块化的方法递增地修改基用例。
见 扩展点(extension point)、包含(include)、用例(use case)、用例泛化(use case generation)
语义
扩展关系联系着基用例和扩展用例。在此关系中,扩展用例不必为独立的可实例化的类元,它只是包含一个或几个片断,用来解说修改基用例所需的行为。扩展关系有一系列扩展点名字,个数与扩展用例中的片断数相等。每个扩展点必须在基用例中定义,当用例实例执行到扩展点所指的基用例的位置,且满足所有扩展用例的控制条件时,实例就转入与扩展用例的片断相对应的行为序列中;扩展片断执行完毕后,控制从转换点返回原始用例。
一个基用例可以有多个扩展用例,用例实例的生命期中可以经过多次扩展。如果多个扩展用例从基用例的同一个扩展点处展开,则它们的行为顺序是不可知的。一对扩展和基用例之间可以有多个扩展关系,只要扩展是从基用例的不同位置插入的就可以了。扩展可以嵌套。
扩展关系中的扩展用例可以访问并修改基用例中定义的属性。但是,基用例看不到扩展用例,不能访问它的属性和操作。基用例定义了可添加扩展的模型框架,但是基用例看不到扩展用例。扩展改动了基用例的行为。请注意它与用例泛化的区别。在扩展中,扩展用例在基用例的一个实例中增加新的行为。在泛化中,子用例的实例增加父用例中没有的新行为,父用例不受子用例的影响。
一个扩展用例可以扩展多个基用例,一个基用例可以被多个扩展用例扩展。这并不表示这些基用例之间有特殊关系。
在扩展、包含或者泛化关系中,扩展用例可以作为自身的基用例。
结构(扩展用例)
扩展用例包括一列插入片断,每个片断是一个行为序列。
结构(基用例)
基用例定义了一些扩展点,每个点是基用例中一个或者一列可以插入行为的位置。
结构(扩展关系)
扩展关系有一系列扩展名字,它们必须在基用例中出现。名字的数目必须与扩展用例中的片断数目相一致。
扩展关系可以有控制条件,基类属性表达式,或者事件的发生,如收到信号。当用例实例执行到达一个扩展点时,控制条件决定是否执行扩展。如果没有控制条件,则认为它为true。如果满足用例的控制条件,将执行扩展。如果引用了基用例中的多个位置,则可能在其中任何一个上进行扩展。
如果控制条件一直为true,扩展可以多次执行。扩展用例的每个片断执行相同的次数。如果必须限制执行次数,可以使用相应的控制条件。
执行语义
当执行基用例的实例达到扩展关系引用的位置时,将计算扩展关系的控制条件。如果条件为true或者为空,则执行扩展。在许多情况下,条件包括某事件的发生或扩展用例片断所需的值出现--例如发出开始扩展的信号。条件可能依赖于用例实例的状态,包括基用例的属性值。如果事件没有发生或者条件为假,则不开始用例的扩展片断。扩展片断执行完毕后,用例实例返回基用例,从刚才离开处继续向下执行。
如果满足控制条件,可以立即执行其他插入的扩展用例。如果扩展点引用基用例的多个位置,其中任何一个的控制条件都可能被满足。在序列中的任何位置,条件都可以为真。
如果一个扩展用例中有多个插入序列,只要控制条件在第一个扩展点被满足,所有扩展片断都将执行。不再为后续片断重新判断扩展条件。后续片断在用例实例到达相应位置时插入。在两个扩展点之间,用例实例返回执行基用例。一旦开始,就必须完成所有片断。
注意:通常用例是不确定的状态机(语法上),而不是可执行的过程。因为控制条件可能需要外部事件的出现。将用例实现为类的合作,需要转换到明确的控制结构中。正如语法的实现需要转换为一种更有效但更难理解的可执行形式。
注意:基和扩展相关的,一个扩展可以是更进一步扩展的基础。这并没有任何困难,上述规则仍然使用--插入是嵌套的。例如,假设用例B在执行扩展点X处扩展了用例A;用例C又在Y点扩展了用例B。(图13-96)。A的实例执行到扩展点X后,开始执行用例B。该实例到达Y点后,开始执行用例C。C执行完成后,返回用例B,扩展B执行完后,再执行返回用例A 。这与嵌套的过程调用或者其他嵌套结构相同。
图13-96 嵌套扩展
图13-97嵌套关系
表示法
从扩展用例向基用例引一虚线箭头,指向基的箭头为树枝形,并带有关键字《extend》。在关键字之后,可以在括号中列出扩展点名字。
图13-97是有扩展关系的用例,图13-98是用例的行为序列。
讨论
扩展、包含、泛化关系都是向原有用例中增加行为。它们有许多共同点,但实际上区分它们很方便。表13-1对于3种视点进行了比较。
图13-98 用例的行为序列
表13-1用例关系的比较
134.扩展点(extension point)引用用例行为序列中一个或一些位置的命名标记,在这些位置可以插入附加行为。扩展点的声明开启了用例扩展的可能性。插入片断是扩展用例的行为序列(与基用例有扩展关联的用例)。扩展关系包括扩展点名列表,它们说明扩展关系的用例片断从何处插入其行为。
见扩展(extend)、用例(use case)。
语义
扩展点有名字,而且引用了用例行为序列中的一个或者几个位置。扩展点可以引用用例的两个行为步骤之间的一个位置。另外,它可以引用一组离散位置。还可以引用行为序列中的一个区域(不超过序列两步之间的所有位置集)。
位置是用例的状态机中的一个状态,或者其他说明方式中的相应成分--在语句列表中的两条语句之间或在交互的两条消息之间。
扩展关系包含可选控制条件和扩展点列表,列表中扩展点的数目与扩展片断数目相等。用例实例执行到基用例的扩展点时,如果条件满足就执行相应的插入片断。
不用改变扩展点的身份标识就可以变换它的位置。使用命名扩展点,可以将扩展
行为序列的说明和基用例的内部细节分开。基用例的修改或重排不会影响扩展。而且扩展点在用例中的移动也不影响关系和扩展用例。对于各类模块,这种独立性需要仔细选择扩展点,而且这种独立性不能在所有情况下都得到保证。
表示法
用例的扩展点可以列在名为extension points的分格内。
扩展点必须也涉及用例行为序列中的一个或者几个位置。也就是说,扩展点名可用作行为序列中状态、语句、区域的标签。但是这并不意味着它存在于行为序列原文中。扩展点是名称,它允许将位置与实现插入的选择分开。编辑工具可以将扩展放到行为序列的覆盖层,而不用修改原文;或者使用映射到语句上扩展点名字的独立列表(使用语句标号,内部标签或者直接图示)。无论如何,最终效果就是将扩展点定位在行为序列中的一步和多步之间。在图13-99的伪代码例中,单括号中的扩展点名引用了行为序列中的一个位置。根据说明序列的语言不同,可以用多种语法为扩展点定位。本例不是唯一的方法 。
图13-99 扩展点声明
135.外延(extent)
由一个描述符描述的一组实例。有时也称为扩展。
反义词:内涵 (intent)。
语义
一个描述符(类或者关联)有解说内容(内涵)和一些被解说的实例(外延)。内涵说明过程外延的实例的属性。外延不一定有物理表示,运行时也不一定能得到。系统不能认为它可以得到类的实例对象。
136.特征(feature)
在类元(如接口、类或数据类型)中,作为表的一部分封装起来的特性,如操作和属性。
137.终态(final state)
组成状态中的一个特殊状态,当它处于活动时,说明组成状态已经执行完成。组成状态进入终态后,将激活离开组成状态的转换,如果满足条件,转换将发生。
见活动(activity)、完成转换(completion transition)、销毁(destruction)
语义
为了实现封装,最好将组成状态的外部效果和内部结构尽可能分开。从外部看,组成状态是不透明的实体,隐藏了内部结构。以外部视图看,转换的起始点和终点都是状态自身。从内部看,转换链接着状态中的子状态。初态和终态是支持状态封装的技术结构。
终态是一个特殊状态,它表明组成状态的活动已经完成,离开组成状态的转换可以开始了。终态不是伪状态。终态可能在一段时间内保持为活动的,这与初态不同。等待组成状态中的其他并行子状态完成时,控制仍保留在终态。
不允许有从终态出发的事件触发转换(否则这就是一般状态)。源于组成状态内的任意多个转换可以进入终态,但不能有源于外部的转换。进入终态的转换是一般转换,可以有触发事件、监护条件和活动。
如果对象到达顶级终态,状态机将终止,对象将销毁。
表示法
终态用牛眼形图标表示--小实心圆外套一个圆环。该符号表示在组成状态内(图13-100)。一个组成状态只能有一个(直接)终态。嵌套状态中,可以有多个终态。为了方便表示,状态中的终态符号可以重复出现,表示相同的终态。
图13-100 终态