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

3
我开始使用状态机实现一个系统。但是,我到了一个质疑状态机是否正确的地步。
例如:我有四个状态:
(空闲,上电,关机,工作)
还有两种其他状态:
(生产,测试)
在生产和测试状态下,上电和关机的行为不同...
如果我有更多的状态,状态的组合会呈指数级增长...
如何用状态机解决这个问题?

在一般情况下这个问题很难回答。但是这些状态变量必须要被表示出来。根据场景不同,这个存储空间可能需要静态地或动态地分配。 - Oliver Charlesworth
5个回答

3
这有点难回答,因为实际用例非常模糊,但这里有一些可能的技术:
1. 为生产 + 上电、测试 + 上电、生产 + 关机、测试 + 关机创建单独的状态。根据状态组合的复杂性和数量,这可能会迅速膨胀。
优点:直接明了。
缺点:混乱,不易扩展,如果某些状态逻辑在多个实例之间共享,则需要进行复制粘贴(因此不易维护)。
2. 使用分层状态机(HFSM),即如果您可以定义各种状态组之间的某种分层关系,则特定状态的实现将是一个独立的状态机。
因此,在您的示例中,您将拥有一个生产/测试状态机,每个状态机都将在内部实现自己的空闲/上电/关机/工作状态机。
优点:比选项1更易读。
缺点:假设子状态应共享某些通用登录信息,仍将涉及复制粘贴。
3. 拥有2个并行状态机,一个处理生产/测试状态,另一个处理空闲/上电/关机/工作状态,并使用某种黑板或共享内存在状态机之间通信。
在您的示例中,您的代理或系统将是上述状态机的容器,并依次处理它们。生产/测试机器将向共享内存写入一些状态,其他机器将从中读取并相应地分支其状态逻辑。
优点:可以在不同状态之间共享代码。
缺点:可以在不同状态之间共享代码...好吧,说真的,强调共享代码并不总是一个好主意(但这是一个完全不同的哲学讨论)。只需确保正确评估共享代码量与唯一代码或路径量之间的比例,以便不会得到一个包含2个完全不同代码路径的巨大类。
4. 我知道这是一个常见做法,但请考虑FSM是否是您的应用程序中表示状态和执行的适当方法。同样,没有足够的上下文来深入探讨这个问题,而且这个问题本身就是一个哲学上的辩论 - 但请保持开放的心态,考虑其他解决方案。

谢谢你的回答!使用案例很模糊,因为它只是一个例子。实际上,在真实应用中会有许多状态机,每个状态机可能有5或6个相互影响的状态,在极端情况下可能有15个或更多的状态。当然,在极端情况下,并不是每个状态都与其他状态“连接”,但会有许多依赖关系...所以,我怀疑状态机是否是最好的方法,因为最终我可能只会“节省”一级混乱,超过这个第一级后,代码将变得混乱和难以阅读,就像以前一样... - zet4080

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

0
一个状态机可以与另一个状态机共享信号。因此,指示prod或dev的状态机可以向另一个状态机发送信号。
实际上,如果您的状态机只有两个状态,您可以使用变量来实现这个目的。因此,您将拥有一个状态机,根据变量的值执行不同的工作。

0

你是否需要同一个状态机模型的两个实例?一个用于生产,一个用于测试?

另一种选择是将生产和测试作为单个状态机的正交区域。


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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接