如何用状态机处理多个状态?

问题描述 投票:0回答:5

我开始实现一个带有状态机的系统。但我怀疑状态机是否是正确的方法。

例如:我有四种状态:

(空闲、通电、断电、工作)

以及其他两个状态:

(生产、测试)

上电和断电在生产和测试状态下的表现确实不同......

如果我确实有更多状态,状态组合就会爆炸......

如何用状态机解决这个问题?

state-machine
5个回答
3
投票

这有点难以回答,因为实际用例非常模糊,但这里有一些可能的技术:

  1. 为生产+通电、测试+通电、生产+断电、测试+断电创建单独的状态。根据状态组合的复杂性和数量,这可能会很快爆炸。

优点:简单。

缺点:混乱,扩展性不好,如果某些状态逻辑在实例之间共享,则会涉及一些复制意大利面(因此,不太可维护)

  1. 使用分层状态机(HFSM),也就是说,如果您可以在各个状态组之间定义某种分层关系,则特定状态的实现将是它自己的状态机。

因此,在您的示例中,您将拥有一个生产/测试状态机,并且每个状态机都将在内部实现自己的空闲/通电/断电/工作状态机。

如果你仔细想想,这实际上是选项 1 的更简洁的实现。

优点:比选项 1 更具可读性

缺点:假设子状态应该共享一些共同的逻辑,仍然会涉及复制粘贴

  1. 有 2 个并行状态机,一个处理生产/测试状态,另一个处理空闲/通电/断电/工作状态,并通过某种黑板或共享内存在机器之间进行通信。

在您的示例中,您的代理或系统将是上述状态机的容器并依次处理它们。生产/测试机器会将一些状态写入共享内存,另一台机器将从该共享内存中读取并相应地分支其状态逻辑。

优点:可以在不同状态之间共享代码

缺点:可以在不同状态之间共享代码...好吧,说实话,强调共享代码并不总是一个好主意非常重要(但这完全是另一个哲学讨论。只要确保您正确评估共享的数量即可代码与唯一代码或路径的数量,这样你就不会得到一个本质上包含 2 个完全独立的代码路径的巨大类

  1. 我知道这是理所当然的,但请考虑一下 FSM 是否是在应用程序中表示状态和执行的正确方法。再说一遍,没有足够的背景来深入探讨这一点,这一点本身就是一场哲学辩论 - 但也要对其他解决方案保持开放的态度。

2
投票

状态机“爆炸”的感觉在传统的“扁平”FSM 中非常典型(事实上,它通常被称为“状态转换爆炸”现象)。补救措施是使用“分层状态机”(HSM)来代替,它专门抵消了传统 FSM 的“爆炸”。基本上,HSM 允许您将具有相似行为的状态组合在一起(在更高级别的超级状态内),从而重用相关状态之间的常见行为。这是一个非常强大的概念,可以带来更加优雅和一致的设计。要了解有关分层状态机的更多信息,可以阅读文章“分层状态机简介”


0
投票

事实上,如果状态机上只有 2 个状态,则可以使用变量来实现该目的。因此,您将拥有一个状态机,它将根据变量的值执行不同的工作。


0
投票

switch(state) { case powerup: switch(mode) { case test: test_powerup_stuff(); break; case production: production_powerup_stuff(); break; default: break; } break; case powerdown: switch(mode) { case test: test_powerdown_stuff(); break; case production: production_powerdown_stuff(); break; default: break; } break; case idle: do_idle_stuff(); break; case work: do_work_stuff(); break; default: state = powerdown; break; }



0
投票

另一种选择是生产和测试可以是单台机器的“正交区域”。

© www.soinside.com 2019 - 2024. All rights reserved.