UML状态图规范说明一、状态图简介状态图(Statechart Diagram)是描述一个实体基于事件反应的动态行为,显示了该实体如何根据当前所处的状态对不同的时间做出反应的。
通常我们创建一个UML状态图是为了以下的研究目的:研究类、角色、子系统、或组件的复杂行为。
状态图用于显示状态机(它指定对象所在的状态序列)、使对象达到这些状态的事件和条件、以及达到这些状态时所发生的操作。
状态机用于对模型元素的动态行为进行建模,更具体地说,就是对系统行为中受事件驱动的方面进行建模(请参见概念:事件与信号)。
状态机专门用于定义依赖于状态的行为(即根据模型元素所处的状态而有所变化的行为)。
其行为不会随着其元素状态发生变化的模型元素不需要用状态机来描述其行为(这些元素通常是主要负载管理数据的被动类)。
状态是对象执行某项活动或等待某个事件时的条件。
对象可能会在有限长度内保持某一状态。
状态具有以下几项特征:二、状态图内容2.1 转移转移是两个状态之间的关系,它表示当发生指定事件并且满足指定条件时,第一个状态中的对象将执行某些操作并进入第二个状态。
当发生这种状态变更时,即“触发”了转移。
在触发转移之前,可认为对象处于“源”状态;在触发转移之后,可认为对象处于“目标”状态。
转移具有以下几项特征:一个转移可能有多个源状态,在这种情况下,它将呈现为一个从多个并行状态出发的结合点;一个转移也可能有多个目标状态,在这种情况下,它将呈现为一个到多个并发状态的叉形图。
2.2 事件触发器在状态机环境中,事件是指可触发状态转移的激励的发生。
事件可能包括信号、调用、时间推移或状态变更。
信号或调用可能具有其值可用于转移的参数,其中包括警戒条件和操作的表达式。
也可能会有无触发器的转移,这样的转移没有事件触发器。
这种转移也被称为完成转移,它们在源状态完成其活动后将被隐含触发。
2.3 警戒条件当转移的触发事件发生时,将对警戒条件进行求值。
只要警戒条件不重叠,就可能会有来自同一源状态并具有同一事件触发器的多个转移。
在事件发生时,只为转移进行一次警戒条件求值。
该布尔表达式可能会引用对象的状态。
2.4 操作操作是可执行的、不可分割的计算过程,这意味着,它不会被事件中断,而会一直运行到结束为止。
它与活动正好相对,因为活动可能被其他事件中断。
操作可以包括操作调用(调用状态机的拥有者以及其他可见对象)、创建或破坏其他对象、或者向另一个对象发送信号。
在发送信号的情况下,信号名称以关键字“send”为前缀。
2.5 进入和退出操作每当进入或退出状态时,进入和退出操作将分别允许发出同一操作。
这可以通过进入和退出操作来顺利地完成,而不必明确地将操作放在每个输入或输出转移上。
进入和退出操作可能没有实参或警戒条件。
位于模型元素的状态机顶层的进入操作可能具有特定的参数,这些参数代表了在创建该模型元素时状态机所接收到的实参。
2.6 内部转移内部转移使事件可以在不退出状态的情况下在状态内得到处理,从而可避免触发进入或退出操作。
内部转移可能会有带参数和警戒条件的事件,它们所代表的基本上是中断处理程序。
2.7 延迟的事件延迟的事件是其处理过程被推迟的事件,它们的处理过程要到事件不被延迟的状态被激活时才会执行。
当该状态被激活时,将触发该事件,同时可能导致转移(好象该事件刚刚发生)。
要实施延迟的事件,需要有事件的内部队列。
如果事件已发生但被列为延迟,它就会被添加到队列中。
当对象进入了不会使事件延迟的状态时,将立即从该队列中取出这些事件。
2.8 子状态简单状态是没有子结构的状态。
具有子状态(嵌套状态)的状态被称为复合状态。
子状态可能被嵌套到任意级别。
嵌套的状态机最多可能有一个初始状态和一个终止状态。
通过显示某些状态只能在特定环境(包含状态)中存在,子状态可以简化复杂的平面状态机。
图3:子状态。
转移的源状态是包含复合状态之外的源状态,其目标状态可能是复合状态或子状态。
如果其目标状态是复合状态,嵌套的状态机就必须包括一个初始状态,在进入复合状态之后并在发出它的进入操作(如果有)之后,控制权将被传递给该初始状态。
如果其目标状态是嵌套状态,那么,在发出复合状态的进入操作(如果有)并发出嵌套状态的进入操作(如果有)后,控制权将被传递给该嵌套状态。
从复合状态出发的转移可能会以复合状态或子状态作为它的源状态。
在这两种情况下,控制权先离开嵌套状态(并在可能的情况下发出它的退出操作),然后离开复合状态(并在可能的情况下发出它的退出操作)。
其源状态为复合状态的转移基本上会中断嵌套状态机的活动。
除非另有指定,当转移进入复合状态时,嵌套状态机的操作将从初始状态开始重新执行(除非转移直接以子状态为目标)。
历史状态使状态机可以重新进入在它退出复合状态之前的最后一个活动子状态。
图 4 显示了如何使用历史状态的示例。
图4:历史状态。
三、常用的建模技术状态机最多地用于建立对象在其生命期内的行为模型。
当对象具有依赖于状态的行为时,尤其需要使用状态机。
可能具有状态机的对象包括:类、子系统、用例、接口(以声明实现该接口的对象必须满足的状态)和协议(以声明实现该协议的对象必须满足的状态)。
并非所有对象都需要有状态机。
如果对象的行为很简单,只是存储或检索数据,那么该对象的行为就与状态无关,它的状态机也没有多少用处。
要建立对象生命期的模型,需要包括三个事项:指定对象可以响应的事件、指定对这些事件作出的响应以及指定过去行为对当前行为的影响。
对象生命期的建模还涉及到确定对象有意义地响应事件的顺序,即从创建对象时开始,继续到该对象被破坏时为止。
3.1 通用准则敏捷建模( AM) ( Ambler 2002)的原则--最大化项目干系人的投资--建议你只有当模型能够提供正面价值的时候才创建模型。
如果一个实体,比如一个类或组件,表示的行为的顺序和当前的状态无关,那么画一个UML状态图可能是没有什么用处的。
例如一个SurfaceAddrESs类就很简单,表示了那些你将会在系统中显示和操作的数据,因此一个UML状态图就没有任何相关之处。
而一个Seminar对象就非常的复杂,学生注册这样一个事件将会根据它的当前状态有不同的反应,就像你在图1中看到的。
图⒈班级注册的一个UML状态图。
3.1.1 把初始状态放置在左上角。
如你在图1所见的,初始状态被建模成一个实心圈,把初始状态放在左上角反映西方人的阅读文化的习惯。
3.1.2 把最终状态放置在右下角。
如你在图1所见,最终状态被建模为一个带边界的实心圆。
把最终状态放右下角反映了西方的文化的从左到右,从上到下的阅读习惯。
3.1.3 状态指南状态是一个实体的行为模式的某个阶段。
状态的表示是通过实体的属性值。
例如,在图1中,当seminar被标记为open,并且存在空位的时候,seminar 就处于Open For Enrollment的状态。
3.1.4 状态名称要简单但应具有描述性。
象Open For Enrollment和PropOSed这种的状态名称很容易理解,从而提高了图⒈的沟通价值。
理论上状态名称应该是现在时,但是用过去式写成的诸如Proposed的名称要比用现在时写成的诸如Is Proposed的名称好的多。
3.1.5 避免"黑洞"状态。
黑洞状态是那种只有变换进来但没有任何变换发出的状态,这种情况要么由于该状态是一个最终状态,要么就是你已经错过了一个或多个变换变换。
3.1.6 避免"奇迹"状态。
奇迹状态是那种只有变换发出但没有任何变换进来的状态,这种情况要么由于该状态是一个起点,要么就是你已经错过了一个或多个变换变换。
3.2 子状态建模指南图1中展示的UML状态图是不完3.2整的,因为它没有建模Seminar的poST - enrollment(注册后)状态。
图2建模了一个Seminar的完整的生命周期,把图1描述为一个新的包括子状态集合的Enrollment的复合状态,也称作超状态。
注意按理说你会像图1的模型那样处理标记,但为了简化起见在原先变换上的标记都没有包括在内。
当一个现有状态表现出复杂的行为时,建模子状态就是有意义的,从而促使你来研究它的子状态。
当几个现有状态共用一个通用的入口条件或出口条件( DouglASs 1999)时,引入超状态是有意义的,在图1中你可以看到所有的状态共用一个通用的closed变换,以到达最终状态。
图⒉Seminar的完整生命周期3.2.1 把通用的子状态变换放在一起和图1中每一个子状态都拥有一个cancelled变换不同,在图2中你可以看到cancelled变换仅用于描述Enrollment超状态,这使图形得到简化。
如果子状态都共享一个入口变换或出口变换,都可以使用一个同样的方法。
变换上的警戒点和动作(如果有)也应该使相等的。
3.2.2 为复杂的实体创建一个分层的状态图虽然这种表现子状态的方法是很好使的,但是最终的图可能变得相当复杂--我们只要设想一下如果Being Taught状态也有子状态的话,图2会变成什么样就知道了。
一个替代的方法是创建一个分层的UML状态图。
例如,图3表示高阶视图,而图1描述了一个细节视图。
这种方法的好处是如果需要的话,马上就可以建立一张详图来研究Being Taught状态。
图⒊Seminar的高阶状态图。
3.2.3 最高阶的状态图总有初始态和最终态一个高阶的UML状态图,例如图2描述的这样,应该表示实体的完整的生命周期,包括"出生"和最后的"死亡"。
低阶的图未必包含初始状态和最终状态,特别是那些建模一个实体的生命周期的"中间状态"的图。
3.2.4 变换和动作变换是从一种状态到另一种状态的序列,它可能是通过一个事件触发的。
简而言之就是被建模的实体的内部或外部的行为。
对一个类来说,变换一般是将会导致状态的重要改变的操作调用的结果,因此我们需要了解一点,并不是所有的方法调用都会导致变换产生的,这一点非常重要。
一个动作就是某个东西,对类来说就是一个操作,被建模的实体所调用的操作。
3.2.4 用实现语言的命名规则命名软件动作图1中的动作遵循Java操作的命名规则( Vermeulen et. 2000),因为系统使用用叙述性文字命名角色动作UML状态图可用于建模非软件实体的生命周期,特别是UML图上的角色。
例如学生角色就可能有诸如Accepted、Full Time、Part Time、Graduated、Masters、Doctoral、和Post - Doctoral等状态,以显示各人的不同行为。
当你在建模现实世界的角色时,与软件中Student类不同的是,状态间的变换最好是使用叙述性文字来描述,例如drop seminar和pay fees,而不是dropSeminar ()和payFees (),因为现实生活中的人是做事情,而不是执行操作。