目录
1、概述
2、事件分类
2.1、信号
2.2、调用事件
2.3、时间事件和变化事件
2.4、发送和接收事件
3、常用建模技术
3.1、对信号族建模
3.1.1、建立过程
3.2、对异常建模
在状态机语境中,使用事件对能够触发状态转移的激励建模。事件包括信号、调用、时间推移或状态改变。
事件可以是同步的,也可以是异步的,因此对事件的建模涉及对进程和线程的建模。
在UML中,每件发生的事情都被建模为一个事件。事件是对在时间和空间上占据一定位置的有意义的发生的规约。信号、时间推移和状态改变是异步事件,表示能在任何时间发生的事件。调用一般是同步事件,表示对一个操作的引用
上图允许可视化事件的声明(如信号OffHook)以及用来触发一个状态转移的事件的使用(如信号OffHook,它导致了从Active到Idle的状态转移及对动作dropConnection的执行)。
1、概述
事件(event)是对一个在时间和空间上占有一定位置的有意义的发生的规约。
在状态机的语境中,一个事件是一次激励的发生,激励能够触发状态转移。
信号(signal)是一种事件,表示在实例间进行通信的异步消息的规约。
事件可以是内部的事件或外部的事件。外部的事件是在系统和它的参与者之间传送的事件。例如,一个按钮的按下和一个来自碰撞传感器的中断都是外部事件。内部事件是在系统内部的对象之间传送的事件。溢出异常是一个内部事件的例子。
2、事件分类
2.1、信号
消息是一个具名对象,它由一个对象异步地发送,然后由另一对象接收。信号是消息的类目,它是消息的类型。
信号和简单类有许多共同之处。
1)信号有实例,尽管一般不需要对其实例进行显式的建模。
2)信号还可以包含在泛化关系中,以便对事件的层次结构建模,有些信号是一般的(如信号NetworkFailure),有些信号是特殊的(如对NetworkFailure的一个特WarehouseServerFailure)。像类一样,信号也可以有属性和操作。在一个对象发送它之前或者在另一个对象接收之后,信号只是一个普通的数据对象。
对象的创建和撤销也是一种信号
信号的属性以它的参数形式出现。例如,当发送一个信号Collision时,可以用参数的形式说明它的属性值,例如Collision(5.3)。
信号可以由状态机中转移动作来发送。也可以把信号建模为交互中的两个角色间的消息。方法的执行也可以发送信号。事实上,当为一个类或一个接口建模时,说明该元素行为的一个重要部分就是说明它的操作所能发送的信号
可以将信号建模为衍型化的类。可以用一个衍型为send的依赖来表示一个操作发送了一个特定的信号。
2.2、调用事件
一个调用事件表示对象接收到一个操作调用请求。调用事件可能触发状态机中的一个状态转移,或者调用目标对象的一个方法。这种选择由类定义中的操作定义来说明。
信号是一个异步事件,而调用事件一般是同步的。调用也可以异步
当一个对象调用另一个具有状态机的对象的一个操作时,控制就从发送者传送到接收者,该事件触发转移,完成操作后,接收者转移到一个新的状态,控制返还给发送者。如果调用者无需等待回应,那么可以把这个调用指定为异步调用。
2.3、时间事件和变化事件
1)时间事件是表示一段时间推移的事件。
在UML中,用 关键字after ,后面跟着计算一段时间的表达式来对一个时间事件建模。表达式可
以是简单的(如 after 2 seconds),也可以是复杂的(如 after 1 ms sinceexiting Idle)。
使用 关键字at 来指出在某个绝对时间点上发生的时间事件。例如,时间事件 at(1 Jan 2005,1200 UT)指出该事件发生在格林尼治时间2005年1月1日的中午。
2)变化事件是表示状态的一个变化或某些条件得到满足的事件。
在UML中,用关键字when后面跟随布尔表达式来对一个变化事件建模。
可以用这样的表达式连续地进行测试(如when altitude < 1000)。
一旦某个条件的值从假变为真,就会引发变化事件。
当条件的值由真变为假时,不会引发变化事件。
当事件一直为真时,不会重复地引发变化事件。
2.4、发送和接收事件
信号事件和调用事件至少涉及两个对象:一个是发送信号或调用操作的对象,另一个是事件指向的对象。因为信号是异步的,而且异步调用本身也是信号,所以事件的语义与主动对象和被动对象的语义是相互影响的。
在某些情况下,可能想要显示一个对象向一组对象发送信号(多点传送),或者向系统中的监听对象发送信号(广播)。对多点传送建模时,应显示一个对象向一组接收者集合上发送信号。对广播建模时,应显示一个对象,它发送信号到代表整个系统的另一个对象。
在UML中,将一个对象可能接收的调用事件建模为这个对象的类的操作。
在UML中,可以通过在类的附加栏中对信号命名来为对象可能接收的具名信号进行建模,
也可以将具名信号以相同的方式附加到一个接口上。
3、常用建模技术
3.1、对信号族建模
在大多数事件驱动的系统中,信号事件是分层的。
例如,一个自主机器人可以辨别外部信号(如 Collision)和内部信号(如 HardwareFault)。不过,内部信号和外部信号未必是互斥的。
例如,信号 HardwareFault 可以进一步特化为BatteryFault 和MovementFault。这些信号甚至还可以进一步被特化,如 MotorStall 是MovementFault的一种。
以这种方式对信号的层次建模,可以说明多态的事件。
例如,考虑一个状态机,它有一个仅当接收到 MotorStall 才能触发的转移。作为这个层次中的叶子信号,该转移只能被这个信号触发,因此它不是多态的。
相反,假如状态机存在一个由HardwareFault的接收所触发的转移,则这个转移是多态的。它能被一个 HardwareFault 或它的任何一种特化信号(包括BatteryFault、MovementFault和MotorStall)触发。
3.1.1、建立过程
- 考虑一组给定的主动对象可能响应的所有不同种类的信号。
- 寻找信号的公共种类,并使用继承将它们放在一般/特殊层次结构中。提升较为一般的信号层次,降低较为特殊信号层次。
- 在这些主动对象的状态机中寻找多态性,在发现多态性的地方,必要时通过引入中间的抽象信号来调整层次结构。
上图是对一个由自主机器人处理的信号族建模。注意根信号(RobotSignal)是抽象的,它没有任何直接的实例。这个信号有两个具体的直接特化信号(Collision 和HardwareFault),其中HardwareFault还被进一步特化。注意信号 Collision有一个参数。
3.2、对异常建模
可视化、详述和文档化类或接口的行为的一个重要部分是说明它的操作所能产生的异常情况。如果交给你一个类或接口,可以调用的操作是很清楚的,但每个操作可能引发的异常则不清楚,除非显式地对它们建模。
在 UML 中,异常发生只是一种额外的事件,建模为信号。出错事件可以附加到操作的说明中。
上图是对异常的一个层次结构建模,这些异常是由容器类(如模板类Set)的标准库产生的。
这个层次结构以抽象信号 Error 为根,它包括 3 种特殊错误:Duplicate、Overflow和Underflow。
操作add可能引发信号Duplicate和Overflow,
操作remove仅引发信号 Underflow。
换一种做法,可以通过在每个操作的规约中命名异常,将这些依赖放置在后台中。不论哪种方法,通过了解每个操作可能发送的所有信号,就可以创建正确地使用类Set的客户端。
虚线矩形框表示模板类
异常发生信号在内的所有信号都是对象之间的异步事件。