目录
1、概述
2、状态
2.1、状态的组成
3、转移
3.1、转移的组成
4、高级状态和转移
4.1、进入效应和退出效应
4.2、内部转移
4.3、do活动
4.4、延迟事件
4.5、子状态机
5、子状态
5.1、非正交子状态
5.2、历史状态
5.3、正交子状态
6、分叉与汇合
7、主动对象
8、常用建模技术
8.1、为对象生命周期建模
使用交互,可以对共同工作的对象群体的行为建模。
使用状态机,可以对单个对象的行为建模。
状态机是一个行为,它说明对象在它的生命期中响应事件所经历的状态序列以及对那些事件做出的反应。
状态机对系统的动态方面建模,
描述一个类、一个用况或整个系统的实例的生命期。这些实例可能响应诸如信号、操作或计时这样的事件。当事件发生时,某些效应将依赖对象的当前状态而发生。
效应(effect)是对状态机中的行为执行的规约。效应最后将细化为某些引起对象状态改变或值的返回的动作的执行。对象的状态(state)是指对象满足某些条件、执行某些活动或等待某些事件的一段时间。
可以用两种方式来可视化执行的动态:
1)一种是强调从活动到活动的控制流(使用活动图)
2)另一种是强调对象可能呈现的状态和这些状态之间的转移(使用状态图)。
在一个对象的生命期中,可能出现各种各样的事件,如信号、操作的调用、对象的创建和撤销、时间的推移或某些条件的改变。
在响应这些事件时,对象通过某些动作(某种计算)做出反应,这些动作导致对象状态改变。
可以使用状态机来对任何建模元素(通常是类、用例,或是整个系统)的行为建模。状态机可以用状态图来可视化。可以关注由事件引发的对象行为,这对反应式系统建模很有用。
1、概述
状态机 (state machine)是一种行为,它说明对象在它的生命期中响应事件所经历的状态序列以及它们对那些事件的响应。
状态 (state)是指对象的生命期中的条件或状况,在此期间对象将满足某些条件、执行某些活动或等待某些事件。
事件 (event)是对一个在时间和空间上占有一定位置的有意义的发生的规约。在状态机的语境中,一个事件是一个激励的发生,它能够触发一个状态转移。
转移 (transition)是两个状态之间的一种关系,它指明对象在第一个状态中执行一定的动作,并当特定事件发生或特定的条件满足时进入第二个状态。
活动 (activity)是状态机中进行的非原子执行。
动作 (action)是一个可执行的原子计算,它引起模型状态改变或值的返回。
图形上,状态用一个圆角的矩形表示,转移用一条从源状态指向新状态的有向实线表示。
用状态机能最好地说明对象的行为必须响应异步消息,或者它的当前行为依赖于过去。这包括能够接收信号的类的实例,其中包括许多主动对象。
可以用状态机来对接口的行为建模
2、状态
状态是对象的生命期中的一个条件或状况,在此期间对象将满足某些条件、执行某些活动或等待某些事件。
2.1、状态的组成
(1)名称(name)一个将本状态与其他状态区分开的文本串;状态可以是匿名的,即没有名称。
(2)进入/退出效应(entry/exit effect)分别为进入和退出该状态时所执行的动作。
(3)内部转移(internal transition)不导致状态改变的转移。
(4)子状态(substate)状态的嵌套结构,包括非正交(顺序活动)或正交(并发活动)子状态
(5)延迟事件(deferred event)指在该状态下暂不处理,将推迟到该对象的另一个状态下排队处理的事件列表。
在对象的状态机中有两个可能要定义的特殊状态。第一个是初始状态,表示状态机或子状态的默认开始位置。初始状态用一个实心的圆表示。第二个是最终状态,表示该状态机或外围状态的执行已经完成。最终状态用一个内部含有一个实心圆的圆圈表示(牛眼睛)。
初始状态和最终状态实际上都是伪状态。它们除了名称外,都没有正规状态的通常部分。
3、转移
转移是两个状态之间的一种关系,表示对象在某个特定事件发生而且特定的条件满足时将在第一个状态中执行一定的动作,并进入第二个状态。
当状态发生这样的转变时,转移被称作激活了。
在转移激活之前,称对象处于源状态;激活后,则称对象处于目标状态。
例如,当 tooCold(带有参数desiredTemp)这样的事件发生时,Heater可能从Idle状态转移到Activating状态。
3.1、转移的组成
(1)源状态(source state)即受转移影响的状态,如果一个对象处于源状态,当该对象接收到转移的触发事件而且监护条件(如果有)满足时,将激活一个离出的转移。
(2)事件触发器(event trigger)是一个事件,源状态中的对象识别了这个事件,则在监护条件满足的情况下激活转移。
(3)监护条件(guard condition)是一个布尔表达式,当因事件触发器的接收而触发转移时,对这个布尔表达式求值:若表达式取值为真则激活转移;若为假则不激活,此时若没有其他的转移能被这个事件触发,则该事件丢失。
(4)效应(effect)是一个可执行的行为(比如动作),它可以直接作用于拥有状态机的对象,并间接作用于对该对象可见的其他对象。
(5)目标状态(target state)即在转移完成后的活动状态。
一个转移可能有多个源(在这种情况下,它表示来自多个并发状态的一个汇合),
也可能有多个目标(在这种情况下,它表示发往多个并发状态的一个分岔)
可以用一个衍型为send 的依赖来显式地显示一个信号发送到的对象,
该依赖的源为状态,目标为这个对象。
4、高级状态和转移
高级特征包括进入效应、退出效应、内部转移、do 活动和延迟事件。
这些特征作为一个文本串显示在状态符号的文本分栏内。
4.1、进入效应和退出效应
每当进入一个状态时,执行某个设置动作;当离开一个状态时,执行某个清理动作。
在状态符号中包括一个进入效应(以关键字entry标记)和一个退出效应(以关键字exit标记
),各自带有一个适当的动作。每当进入该状态时,就执行它的进入动作;每当离开该状态时,就执行它的退出动作。
4.2、内部转移
一旦处于一个状态内,将遇到想在不离开该状态的情况下处理的事件,这被称为内部转移(internal
transition)。它通过执行一个效应来响应事件,但不改变状态。而且不执行进入或退出动作。
关键字 entry、exit和 do都是保留字,不能用作事件的名字。
4.3、do活动
当对象处于一个状态时,它一般是空闲的,在等待着一个事件的发生。希望对一个持续的活动建模。在处于一个状态的同时,对象做着某些工作,并一直继续直到被一个事件所中断。
4.4、延迟事件
在3.1图中,假定只有一个离开这个状态、并由事件contact触发的转移。当处于Tracking状态时,除了事件contact和那些由其子状态处理的事件之外,其他事件都将被丢弃。也就是说事件可以发生,但它将被忽略,而且不因为该事件的出现而产生任何动作。
延迟事件的实现需要有一个内部事件队列。如果一个事件发生,并被列为延迟事件,则进入队列。一旦对象进入一个不延迟这些事件的状态,这些事件就会从这个队列中取走。
4.5、子状态机
在一个状态机中可以引用另一个状态机。被引用的状态机称为子状态机(submachine)。
5、子状态
组合状态既可能包含并发(正交的)子状态也可能包含顺序(非正交的)子状态。
5.1、非正交子状态
上图表示通过使用嵌套子状态,Active状态有一个子结构,包括子状态Validating、Selecting、Processing和Printing。当顾客将信用卡插入ATM机时,ATM的状态从Idle转移到Active。在进入Active状态时,执行进入动作readCard。从子结构的初始状态开始,控制从 Validating 状态传递到Selecting 状态,再到 Processing 状态。在 Processing 状态之后,控制可能返回到Selecting状态(如顾客选择另一个事务)或可能转移到Printing状态。在Printing状态之后,有一个完成转移返回到 Idle状态。注意,Active状态有一个退出动作来吐出顾客的信用卡。
由cancel事件触发的从Active状态到Idle状态的转移。在Active的任何子状态中,顾客都可能取消这个事务,并使ATM返回到Idle状态。
非正交子状态将组合状态的状态空间分成一些不相交的状态。
一个嵌套的非正交状态机最多有一个初始子状态和一个最终子状态。
5.2、历史状态
想要它记住在离开组合状态之前最后活动着的子状态
例如,在对一个通过网络进行无人值守的计算机备份的代理的行为建模时,如果它曾被中断(例如,被一个操作员的查询中断),希望它记住是在该过程的什么地方被中断的。
用一个包含符号H的小圆圈来表示一个浅历史状态。
允许一个包含非正交子状态的组合状态来记住源自组合状态的转移之前最后的活动子状态。
在上图中,假定处于BackingUp和Copying状态中时,事件query被发出。控制离开Copying和BackingUp(必要时执行其退出动作),并返回到Command状态。当Command的动作完成后,完成转移返回到组合状态BackingUp的历史状态。这一次,由于这个嵌套状态机有了历史,所以控制传回到Copying状态(绕过了Collecting状态),因为Copying是从BackingUp转移之前的最后一个活动子状态。
符号H表示浅历史,它只记住直接嵌套的状态机历史。
符号H*的小圆圈表示深历史。深历史将在任何深度上记住最深的嵌套状态。
如果仅有一层嵌套,那么深历史和浅历史状态在语义上是等同的。
如果有多于一层的嵌套,那么浅历史只能记住最外层的嵌套状态,而深历史则可以在任何深度上记住最深层的嵌套状态。
5.3、正交子状态
在一个对象的语境中并行执行的两个或多个状态机。
上图显示了对图5.1中的Maintenance状态的一个扩展。
Maintenance被分解为两个正交区域:Testing和Commanding,它们在Maintenance状态中嵌套显示,并用一条虚线分开。
每个正交区域进一步分解为非正交子状态
当控制从 Idle 状态传送到Maintenance状态时,控制就分岔为两个并发的流——这个对象将同时处于Testing区域和Commanding区域。而且,当处于 Commanding区域时,这个对象将处于 Waiting状态或者Command状态。
6、分叉与汇合
下图它从Idle状态转到两个嵌套状态,即Self diagnose和区域Commanding的最终状态。(最终状态也是一个真实的状态,可以作为转移的目标)。如果在Self diagnose状态活动时发生了错误,就会激活到Repair的隐式的汇合转移:无论是Self diagnose状态,还是Commanding区域内的任意活动状态都会被退出。
图中还有一个到状态Offline的显式的汇合转移。只有当 Testing devices 状态和 Commanding 区域的最终状态是活动的,而且disconnect事件发生,才会激活这个转移;如果两个状态都不活动,则该事件无效。
7、主动对象
对并发建模的另一种方式是使用主动对象。因而,不是把一个对象的状态机划分成两个或多个并发区域,而是定义两个主动对象,每个负责一个并发区域的行为。
如果这些并发控制流中的一个控制流的行为受到其他控制流状态的影响,就用正交区域来建模。
如果这些并发流中的一个控制流的行为受到与其他控制流来往的消息的影响,就用主动对象来建模
如果并发流之间的通信很少或根本就没有,那么选择哪种建模方法就全凭个人感觉了,通常用主动对象建模会使设计决策更明显。
8、常用建模技术
8.1、为对象生命周期建模
交互用来对一起工作的对象群体的行为建模
而状态机用来对单个对象的整个生命期的行为建模
主要描述以下3种事物:
1)对象能够响应的事件,
2)对这些事件的响应,
3)过去对当前行为的影响。
为对象的生命期建模,还包括决定该对象能够有意义地响应事件的次序,从对象的创建时开始,一直到它被撤销。
建立过程:
- 设置状态机的语境,不管它是一个类、一个用况,还是整个系统。
- 如果语境是一个类或一个用况,则找出相邻的类,包括这个类的所有父类和通过依赖或关联到达的所有类。这些邻居是动作的候选目标或在监护条件中包含的候选项。
- 如果语境是整个系统,则将注意力集中到这个系统的一个行为上。理论上,系统中每个对象都可以是系统生命期模型中的一个参加者,而且除了最微小的系统之外,建立一个完整的模型将是非常棘手的。
- 建立这个对象的初始状态和最终状态。为了指导模型的剩余部分,可能要分别声明初始状态和最终状态的前置条件和后置条件。
- 判断这个对象可能响应的事件。如果已经说明,则将在对象的接口中发现这些事件;如果还没说明,就要考虑在语境中哪个对象可能与该对象交互,然后发现它们可能发送哪些事件。
- 从初始状态开始到最终状态,列出这个对象可能处于的顶层状态。用由适当的事件触发的转移将这些状态连接起来,接着向这些转移中添加动作。
- 识别任何进入动作或退出动作(尤其当发现它们所适用的惯用法被用于状态机时)。
- 如果需要,通过使用子状态来扩充这些状态。
- 检查在状态机中提供的所有事件是否和该对象接口所期望的事件相匹配。类似地,检查该对象的接口所期望的所有事件是否都被状态机所处理。最后,留意明显地想忽略这些事件的地方。
- 检查在状态机中提到的所有动作是否由对象的关系、方法和操作所支持。
- 通过跟踪状态机(不管是手工地还是通过工具),根据期望的事件顺序及其响应进行检查。尤其要努力寻找那些不可达状态和可能导致机器停止的状态。
- 在重新安排状态机之后,按所期望的顺序再一次检查,以确保没有改变该对象的语义。
上图在这个控制器类的生命期中有 4个主要的状态:
“初始化”Initializing(控制器开始运行)、“空闲”Idle(控制器准备好,并等待警报或来自用户的命令)、“命令”Command(控制器正在处理来自用户的命令)和“活动”Active(控制器正在处理一个警报条件)。
当第一次创建这个控制器对象时,首先进入Initializing状态,然后无条件地进入Idle状态。这两个状态的详细信息并不显示,但要显示Idle状态中带有时间事件的自转移。
这种时间事件在嵌入式系统中是常见的,它常常有一个心跳定时器,每隔一段时间就检查一下系统的健康状况。
当接收到一个“警报”alarm事件(包括参数s,表示发生错误的传感器)时,控制从Idle状态转移到Active状态。
进入Active状态时,setAlarm作为进入动作执行,控制首先传送到Checking状态(验证这个警报),然后传送到Calling状态(呼叫警报公司以登记这个警报),最后传送到Waiting 状态。仅当“清除”clearing 警报时,或是用户向控制器发“注意”attention信号以通知可能发布一个命令时,才退出状态Active和Waiting。
注意这里没有最终状态。这在嵌入式系统中也是常见的,希望系统无限期地运行。