5.7 实现状态图
状态图通常用来为子系统、控制对象或者实体对象建模。总共有两种方法可用来实现状态图。
● 使用程序中的某个位置来保存状态;
● 使用明确的属性来保存状态。
第1种方法适合于实现主动对象或者子系统这类的主动实体的状态图。这是因为主动实体通过使用像if-then-else和while这类的控制语句已经具备自己的控制流逻辑。这种方法类似于前面描述的活动图实现方法。
第2种方法适合于实现非主动实体的状态图。可以通过应用以下技术实现状态图。
● 将状态图映射到类。
● 添加状态属性用来存放状态消息。
● 将事件映射到一个方法,并将所需的所有状态转换和事件动作都嵌入到该方法中。
● 对于具有顺序子状态的组合状态来说,有必要创建一个嵌套类(内部类)用来实现这些顺序子状态。父状态机可以调用嵌套类的方法来处理嵌套状态图内部的状态转换。实现组合状态图的另一种方法是将父状态变形,以消除组合状态,这样就变成了一个平面状态图。
● 对于具有并发子状态的组合状态来说,可以创建嵌套类用来实现每个子状态。这种实现方法类似于实现嵌套状态图的方法。当所有并发子状态到达它们的最终状态时,组合状态退出。
换句话说,通过一组处理某个事件的方法来实现状态图。这些方法将更新状态属性,并在触发某个状态转换时,执行适当的动作。每次发生状态转换,都将事件映射成方法,方法中包括对守卫条件的检查以及相关动作(如图5-41所示)。如果某个事件出现在从不同状态产生的状态转换中,那么常常需要switch语句来确定到底应该出现哪一个转换。

图5-41 从状态转换到其实现
5.7.1 实现一个简单的状态图
假设将售卖机的控制对象的状态图作为被动对象(没有自己线程的对象)实现。实际上,将图5-39中给出的活动图转换成一幅等效的状态图(如图5-42所示),然后通过去掉用来分发饮料和找零的并发子状态,以达到简化它的目的。图5-43给出了售卖机控制对象的实现。

图5-42 售卖机控制对象的状态图

图5-43 将事件映射到状态机的一个方法
5.7.2 实现一个具有顺序子状态的状态图
为了演示顺序子状态的实现,通过修改前面例子,将“分发饮料”状态和“找零”状态组合成一个子状态,如图5-44所示。将“分发”子状态作为另一个状态机,并将其作为父状态机中的内部类实现(如图5-45和图5-46所示)。

图5-44 具有顺序子状态的状态图

图5-45 “分发”子状态的实现

图5-46 售卖机控制对象的实现







