状态机表示

时间:2012-12-07 13:01:03

标签: c++ state-machine

我想将GUI实现为状态机。我认为这样做有一些好处和一些缺点,但这不是这个问题的主题。

在对此进行一些阅读后,我发现了几种用C ++建模状态机的方法,我坚持使用2,但我不知道哪种方法更适合GUI建模。

  1. 使用以下方法将状态机表示为状态列表:

    • OnEvent(...);
    • OnEnterState(...);
    • OnExitState(...);

    StateMachine::OnEvent(...)我将事件转发到CurrentState::OnEvent(...),此处决定是否进行转换。在转换时,我致电CurrentState::OnExitState(...)NewState::OnEnterState()CurrentState = NewState;

    使用这种方法,状态将与动作紧密耦合,但State从一个状态我可以进入多个状态时可能变得复杂,我必须针对不同的转换采取不同的动作。

    < / LI>
  2. 将状态机表示为具有以下属性的转换列表:

    • InitialState
    • FinalState
    • OnEvent(...)
    • DoTransition(...)

    StateMachine::OnEvent(...)我将事件转发到状态机中InitialStateCurrentState具有相同值的所有转换。如果满足转换条件,则停止循环,调用DoTransition方法并将CurrentState设置为Transition::FinalState

    使用这种方法Transition将非常简单,但过渡计数可能会非常高。此外,当一个州收到一个事件时,跟踪将要采取的行动将变得更加困难。

  3. 您认为哪种方法更适合GUI建模。你知道其他可能对我的问题更好的陈述吗?

5 个答案:

答案 0 :(得分:3)

这是第三种选择:

  • 将状态机表示为转换矩阵
    • Matrix列索引表示状态
    • 矩阵行索引代表symbol(见下文)
    • 矩阵单元表示机器应该转移到的状态。这可能是新州或同一州
    • 每个州都有OnEvent方法,该方法会返回symbol

StateMachine::OnEvent(...)事件转发到State::OnEvent,返回symbol - 执行结果。 StateMachine然后根据当前状态和返回的符号决定是否

  • 必须转换到不同的状态,或
  • 保留当前状态
  • (可选)如果进行了转换,则会针对相应的状态调用OnExitStateOnEnterState

3个状态和3个符号的示例矩阵

0 1 2
1 2 0
2 0 1

在此示例中,如果机器处于任何状态,状态(0,1,2)State::OnEvent将返回符号0(矩阵中的第一行) - 它将保持相同的状态

第二行表示,如果当前状态为0且返回的符号为1,则转换为状态1。对于州1 - &gt;州2和州2 - &gt;州0

类似的第三行表示对于符号2,状态0 - &gt;州2,州1 - &gt;州0,州2 - &gt;州1

这就是:

  1. symbols的数量可能远低于州的数量。
  2. 各国不了解彼此
  3. 所有过渡都是从一个点开始控制的,所以当您想要将符号DB_ERRORNETWORK_ERROR区别对待时,您只需更改过渡表并且不要触及状态实施。

答案 1 :(得分:1)

我不知道这是否是您期望的那种答案,但我会用一种直接的方式来处理这些状态机。

使用枚举类型的状态变量(可能的状态)。在GUI的每个事件处理程序中,测试状态值,例如使用switch语句。做相应的处理,并设置状态的下一个值。

轻巧灵活。保持代码规则使其可读和“正式”。

答案 2 :(得分:1)

我个人更喜欢你说的第一种方法。我发现第二个是非常反直觉和过于复杂的。为每个状态设置一个类很简单,如果你在OnEnterState中设置正确的事件处理程序并在OnExitState中删除它们,你的代码将是干净的,并且所有内容都将自动包含在相应的状态中,以便于读取。

您还将避免使用巨大的switch语句来选择正确的事件处理程序或过程来调用,因为状态所做的一切在状态内部完全可见,从而使状态机代码简短。

最后但并非最不重要的是,这种编码方式是从状态机绘制到您将使​​用的任何语言的精确翻译。

答案 3 :(得分:0)

对于这种代码,我更喜欢一种非常简单的方法。

  • 州的列举。
  • 每个事件处理程序在决定要采取的操作之前检查当前状态。操作只是switch语句或if链中的复合块,并设置下一个状态。
  • 当动作变得超过几行或需要重用时,重构为对单独的辅助方法的调用。

这样就没有额外的状态机管理元数据结构,也没有管理该元数据的代码。只是您的业务数据和转换逻辑。并且操作可以直接检查和修改所有成员变量,包括当前状态。

缺点是您无法添加本地化为单个状态的其他数据成员。除非你有很多州,否则这不是一个真正的问题。

如果您总是在进入每个状态时配置所有UI属性,而不是对先前设置进行假设并创建状态退出行为以在状态转换之前恢复不变量,我发现它还会导致更强大的设计。无论您使用什么方案来实现转换,这都适用。

答案 4 :(得分:0)

您还可以考虑使用Petri网对所需行为进行建模。如果您想要实现更复杂的行为,这将是更可取的,因为它允许您准确确定所有可能的方案并防止死锁。

此库可能对实现控制GUI的状态机很有用:PTN Engine