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