前页 | 后页 |
示例:进入状态
进入状态的状态取决于状态的状态和进入的方式。
在所有情况下,状态的进入行为在状态时执行(如果已定义),但仅在与传入转移
相关联的任何效果行为之后转移
完成了。此外,如果为状态定义了行为,则该行为在执行该条目行为之后立即开始执行。
对于定义了一个或多个区域的复合状态,每个区域存在许多替代方案:
- 默认条目:当拥有复合状态是转移
的直接目标时会发生这种情况转移
;在执行 entry行为并分叉一个可能的行为执行之后,状态entry 通过它的输出转移
从一个初始的 Pseudostate 继续转移
(称为默认转移
的状态),如果它在区域中定义
如果没有定义初始 Pseudostate,则此区域将不会处于活动状态 - 显式入口:如果传入转移
或者它的延续终止于拥有复合状态的直接包含的子态状态,然后该子态状态变为活动状态,并且在包含复合状态的行为执行之后执行其条目行为
如果转移
,则此规则递归适用转移
以间接(深度嵌套)子态终止 - 浅历史入口:如果传入转移
终止于该区域的一个区域Pseudostate,激活的子态状态成为在该进入之前最近处于活动状态的子态状态(除了 FinalState),除非这是进入该状态的第一个条目;如果它是第一个进入这个状态的条目,之前的条目已经到达了一个终点或一个默认的浅历史转移
如果定义了就取,否则应用默认状态入口 - 深度历史条目:这种情况的规则与浅层历史的规则相同,只是目标伪状态的类型为 deepHistory 并且该规则递归地应用于此之下的活动状态配置中的所有级别
- 入口点入口:如果一个转移
通过一个状态Pseudostate进入拥有复合状态,然后向外转移
取自入口点,渗透到该区域内的状态;如果从入口点有更多的传出转换,则每个转移
必须定位到不同的区域并且所有区域同时激活
显式输入一个或多个区域(在分叉或入口点的情况下),这些区域显式输入,其他区域默认输入。
在这个例子中,我们演示了一个具有正交状态的所有这些入口行为的模型。
建模状态机
状态机的上下文
- 创建一个名为MyClass的类元素,作为状态机的上下文。
- 在浏览器窗口中右键单击MyClass并选择“添加|状态机”选项。
状态机
- 在图中添加一个Initial节点、一个名为状态的状态、一个名为 State2的状态和一个名为 final 的终点元素。
- 放大图上的State2 ,右键单击它并选择'高级|定义 Concurrent Substates 的选项,定义RegionB、RegionC、 RegionD和RegionE。
- 右键单击State2并选择“New子元素|入口”选项以创建入口EP1 。
- 在RegionB中,创建元素InitialB ,过渡到StateB1 ,过渡到StateB2 ,过渡到StateB3 ;由事件触发的所有转换B
- 在RegionC中,创建元素 shallow HistoryC (右键单击 History 节点 |高级| Deep History | 取消选中),过渡到StateC1 ,过渡到StateC2 ,过渡到StateC3 ;事件C触发的所有转换。
- 在RegionD中,创建元素 deep HistoryD (右键单击 History 节点 |高级| Deep History | 勾选),过渡到StateD1 ,创建StateD2作为 StateD3 的父级,它是StateD4的父级;从StateD1到StateD4的转换;由事件D触发。
- 在RegionE中,创建元素InitialE ,过渡到StateE1 ,过渡到StateE2 ,过渡到StateE3 ;由事件触发的所有转换E
- 从入口EP1到StateC1和划的划线过渡。
不同条目类型的划转换:
- 默认条目: State1到State2 ;由事件DEFAULT 触发。
- 显式条目: State1到StateB2 ;由事件EXPLICIT 触发。
- 浅历史条目:从State1到HistoryC ;由事件SHALLOW 触发。
- 深度历史条目: State1到HistoryD ;由事件DEEP 触发。
- 入口条目: State1到EP1 ;由事件ENTRYPOINT 触发。
其它转换:
- 复合状态Exit:从State2到State1 ;由事件BACK 触发。
- State1到终点,由事件QUIT 触发。
仿真
工件
Enterprise Architect支持 C、C++、C#、 Java和JavaScript 。我们在此示例中使用JavaScript ,因为我们不需要安装编译器。 (对于其他语言,需要 Visual Studio 或 JDK。)
- 在工具图表的“仿真工具”页面上,将“输入和可执行状态机”的图表工具箱一个工件“状态模拟”的仿真工具上。将语言设置为JavaScript 。
- Ctrl+ 将MyClass从元素浏览器窗口输入到工件属性浏览器中,选择“粘贴作为属性”选项并将名称命名为属性。
代码生成
- 单击EnteringAStateSimulation并选择“仿真> 可执行状态 > 状态机 >生成、编译和运行”功能区选项。
- 为生成的源代码指定一个目录。
运行仿真
温馨提示:您可以在仿真窗口中查看执行序列,您可以通过选择“仿真>动态仿真仿真>模拟器>打开仿真窗口”功能区选项打开该窗口
模拟开始时, State1处于活动状态,状态机正在等待事件。
使用“>仿真动态仿真>事件”功能区选项打开仿真事件(触发器)窗口。
1 ) 选择默认条目:触发器序列[DEFAULT]。
- RegionB被激活,因为它定义了InitialB ;从它发出的转换将被执行, StateB1是活动状态
- RegionE被激活,因为它定义了InitialE ;从它发出的转换将被执行, StateE1是活动状态
- RegionC和RegionD处于非活动状态,因为没有定义初始伪状态
2) 选择显式条目:触发器序列[EXPLICIT]。
- RegionB被激活,因为过渡以包含的顶点StateB2为目标
- RegionE被激活,因为它定义了InitialE ;从它发出的转换将被执行, StateE1是活动状态
- RegionC和RegionD处于非活动状态,因为没有定义初始伪状态
3) 选择默认历史转移
:简单的序列[触发器]
- RegionC被激活,因为过渡以包含的顶点HistoryC为目标;因为这个区域是第一次进入(并且历史伪状态没有什么要“记住”的),所以从历史C到状态C1的转换被执行
- RegionB被激活,因为它定义了InitialB ;从它发出的转换将被执行, StateB1是活动状态
- RegionE被激活,因为它定义了InitialE ;从它发出的转换将被执行, StateE1是活动状态
- RegionD处于非活动状态,因为未定义初始伪状态
- 我们假设浅历史伪状态HistoryC可以记住StateC3
5) 选择Shallow History Entry:简单序列[触发器]。
- 对于RegionC ,直接激活StateC3
6) 选择入口条目:简单的序列[触发器]。
- RegionC被激活,因为从EP1的转换以包含的StateC1为目标
- RegionD被激活,因为从EP1的转换以包含的StateD1为目标
- RegionB被激活,因为它定义了InitialB ;从它发出的转换将被执行, StateB1是活动状态
- RegionE被激活,因为它定义了InitialE ;从它发出的转换将被执行, StateE1是活动状态
- 我们假设深度历史伪状态HistoryD可以记住StateD2 、 StateD3和StateD4
8) 选择深度历史条目:触发器序列[DEEP]。
- 对于RegionD ,输入StateD2 、 StateD3和StateD4 ;痕迹是:
- myClass[MyClass].StateMachine_State1 退出
- myClass[MyClass].StateMachine_State2 ENTRY
- myClass[MyClass].StateMachine_State2 DO
- myClass[MyClass].InitialE_105787__TO__StateE1_61746影响
- myClass[MyClass].StateMachine_State2_StateE1 条目
- myClass[MyClass].StateMachine_State2_StateE1 DO
- myClass[MyClass].InitialB_105785__TO__StateB1_61753影响
- myClass[MyClass].StateMachine_State2_StateB1 条目
- myClass[MyClass].StateMachine_State2_StateB1 DO
- myClass[MyClass].StateMachine_State2_StateD2 条目
- myClass[MyClass].StateMachine_State2_StateD2_StateD3 条目
- myClass[MyClass].StateMachine_State2_StateD2_StateD3_StateD4 条目