C++ 状态机表示
我想将GUI实现为一个状态机。我认为这样做有一些好处,也有一些缺点,但这不是这个问题的主题C++ 状态机表示,c++,state-machine,C++,State Machine,我想将GUI实现为一个状态机。我认为这样做有一些好处,也有一些缺点,但这不是这个问题的主题 在阅读了有关这方面的文章后,我发现了几种在C++中建模状态机的方法,我坚持了2种方法,但是我不知道哪种方法能更好地用于GUI建模。 使用以下方法将状态机表示为状态列表: OnEvent(…) onenternstate(…) OnExitState(…) 从StateMachine::OnEvent(…)我将事件转发到CurrentState::OnEvent(…),在这里决定是否进行转换。在转换时,
在阅读了有关这方面的文章后,我发现了几种在C++中建模状态机的方法,我坚持了2种方法,但是我不知道哪种方法能更好地用于GUI建模。
OnEvent(…)代码>
onenternstate(…)代码>
OnExitState(…)代码>
StateMachine::OnEvent(…)
我将事件转发到CurrentState::OnEvent(…)
,在这里决定是否进行转换。在转换时,我调用CurrentState::OnExitState(…)
,NewState::oneterstate()
和CurrentState=NewState代码>
通过这种方法,状态将与动作紧密耦合,但是当我从一个状态转到多个状态,并且我必须为不同的转换采取不同的动作时,state
可能会变得复杂
InitialState
FinalState
OnEvent(…)
DoTransition(…)
StateMachine::OnEvent(…)
I将事件转发到所有转换,其中InitialState
与状态机中的CurrentState
具有相同的值。如果满足转换条件,则循环停止,DoTransition
方法被调用,并且CurrentState
设置为transition::FinalState
使用这种方法,转换
将非常简单,但转换计数的数量可能会非常高。此外,当一个国家收到一个事件时,跟踪将采取的行动也将变得更加困难您认为哪种方法更适合GUI建模。你知道其他可能更适合我的问题的表示法吗?我不知道这是否是你所期望的答案,但我用一种简单的方式处理这种状态机 使用枚举类型的状态变量(可能的状态)。在GUI的每个事件处理程序中,测试状态值,例如使用switch语句。相应地执行任何需要的处理,并设置状态的下一个值
轻便灵活。保持代码的规则性使其可读性和“正式”。我个人更喜欢你说的第一种方法。我发现第二种方法非常违反直觉,过于复杂。为每个状态设置一个类非常简单,如果您在OneInterState中设置了正确的事件处理程序,并在OnExitState中删除它们,那么您的代码将是干净的,并且所有内容都将在相应的状态中自包含,从而易于阅读 您还将避免使用大量switch语句来选择要调用的正确事件处理程序或过程,因为状态所做的一切在状态本身内部都是完全可见的,从而使状态机代码简短而简单
最后但并非最不重要的一点是,这种编码方式是从状态机绘图到您将使用的任何语言的精确转换。这里是第三种选择:
- 将状态机表示为转移矩阵
- 矩阵列索引表示一个状态
- 矩阵行索引表示符号(见下文)
- 矩阵单元表示机器应转换到的状态。这可能是新状态,也可能是同一状态
- 每个州都有
方法,该方法返回一个OnEvent
符号
StateMachine::OnEvent(…)
事件被转发到State::OnEvent
,它返回一个符号
——执行的结果<代码>状态机然后根据当前状态和返回的符号决定
- 必须转换到不同的状态,或者
- 当前状态被保留
- 或者,如果进行了转换,则为相应的状态调用
和OnExitState
oneterstate
0 1 2
1 2 0
2 0 1
在此示例中,如果机器处于任何od状态,则状态(0,1,2)
和状态::OnEvent
返回符号0
(矩阵中的第一行)-它保持在相同的状态
第二行表示,若当前状态为0
,返回的符号为1
,则转换为状态1
。对于状态1
->状态2
和状态2
->状态0
类似地,第三行表示符号2
,状态0
->状态2
,状态1
->状态0
,状态2
->状态1
这一点是:
符号的数量可能会比州的数量少得多
DB\u错误
和NETWORK\u错误
时,您只需更改转换表,而不涉及状态实现对于这种代码,我更喜欢一种非常简单的方法
- 国家的列举
- 每个事件处理程序在决定采取何种操作之前检查当前状态。动作只是
语句或开关
链中的复合块,并设置下一个状态if
- 当动作的长度超过几行或者需要重用时,重构为调用单独的helper方法