40

我想知道状态机是否只是工作中的状态模式,或者这两者之间是否真的有区别?

我发现这篇文章的标题是“状态设计模式与状态机”,但最后他只说状态模式使状态机过时,但没有描述与状态机相比究竟是什么状态机执行状态模式

4

7 回答 7

23

我向同事描述这种差异的方式是,状态模式是许多独立封装状态的更加分散的实现,而状态机更加单一。状态机的整体性意味着单个状态将更难在不同的机器中重用,并且更难将状态机分解为多个编译单元。另一方面,这种单片设计允许更好地优化状态机,并允许许多实现在表中的一个位置表示所有转换信息。这尤其适用于负责状态机架构或功能的人员不精通其实现的编程语言的情况。请记住,许多工程和数学专业的学生已经了解了状态机,但在编程领域几乎没有受过教育。向这些类型的人展示转换、动作和守卫的表格比一页一页的状态模式要容易得多。

虽然这篇文章实际上读得很好,但我在以下几点上不同意作者的观点:

请注意,切换状态需要分配!这将扼杀速度。这可以通过将缓冲区中的所有状态彼此相邻的布局来解决,以节省一两次缓存未命中。但是,这将需要对 Authors 示例进行重大更改。

另请注意,未处理的事件不能像在静态状态机中那样被内联和优化掉,因为在状态模式下,它们位于动态间接层的后面。根据您的要求,这也是一个潜在的效率杀手。

从维护的角度来看,应该注意记录未处理的事件不能从具有状态模式的一个中央超状态完成。此外,添加新的事件类型/处理函数需要向所有状态添加一个函数!我不认为维护友好。

我也更喜欢查看表格中的所有转换,而不是查看每个状态的内部运作。作者是对的,添加状态更容易,但只是非常少,例如提升状态图我只需将状态添加到其父子状态列表中,这是唯一真正的区别。

在速度不是问题并且状态机的层次结构很可能保持平坦的情况下,我确实使用状态模式。作者是正确的,与状态机相比,状态模式的初始实现通常更容易,并且通常更多的程序员应该使用更多的状态机。

状态模式的一个论点是它允许实现“打开关闭”状态机,其中状态机可以在库中定义然后由用户扩展,据我所知,这是不可能的主流状态机构架。

于 2013-12-07T21:35:00.677 回答
14

In case anyone still interested, here is my view:

In state machine, the object can be in different states, but we don't really care how they behave in those states. In fact, we only care what action is applied when the object is transitioned to the next state. If you implement a state machine in Java, a state will be just an enum, or a String and there will be a Transition class with doAction() method.

On the other hand, in state pattern, you don't really care about the transition, but how the object behave in those states. The transition is just an implementation details to make your state behaviors decoupled from each other. Each state will be a separate class, having doAction() method of its own.

Saying state pattern makes state machine obsolete is incorrect. State pattern will be useful if the behavior of each state is important, e.g in game programming, where an object can have states like "idle", "attack", "run" and in each state you want to implement the behavior of the object.

But for use case like ordering online products, where you don't care how the order object behaves. You only care if the order is in "added_to_cart" state, when a "payment_finished" event is published, then change it to "processing" state. In this case state is a simple enum property of the Order class, thus using state machine is much better.

于 2018-04-25T15:28:07.423 回答
10

可以通过多种方式设计和实现状态机。一种方法是使用四人帮在书中描述的状态模式。但是还有其他模式可以实现状态机。

例如,您可能想通过阅读Practical UML statecharts in C/C++, 2nd ed 一书了解 Miro Samek 的研究。(嵌入式系统的事件驱动编程)

您可能还会发现这个问题很有趣。

于 2013-11-08T13:11:57.987 回答
2

我注意到状态模式有所不同。将它用于 UI 时更方便。可以说我想锁定状态。在状态模式上下文中,我可以创建一个布尔值并防止状态进一步改变。

这是一个 Kotlin 示例:

     inner class StateContext : State {

       private var stateContext: State? = null
       private var lockState: Boolean = false

       fun isLockState(): Boolean {
           return lockState
       }

       fun setLockState(lockState: Boolean): StateContext {
           this.lockState = lockState//no further actions allowed. useful if you need to permenatley lock out the user from changing state.
           return this
       }

       fun getState(): State? {
           return this.stateContext
       }

       fun setState(state: State): StateContext {
           if (!lockState) this.stateContext = state
           return this
       }

       override fun doAction() {
           this.stateContext?.doAction()
       }
   }

使用状态机我不确定如何轻松完成。

当我只关心状态(例如保存当前状态的枚举)而不是实际的实现细节(例如更改 UI 按钮颜色)时,我真的很喜欢状态机。状态机的优点之一是您可以有一个中心位置来记录状态更改。我通过 tinder看到了这个 kotlin 库,看起来很有趣。但我个人认为您可以将它们全部更改为您想要的,只是一种方式比另一种方式更清洁。

那什么是状态机?stateMachine 更关心“下一个状态是什么”,它强调状态的转换而不是它的细节。它保持流动。通常你使用枚举创建它。这篇文章有助于清除它(下面的参考资料是从那里获取的以帮助清除差异),但本质上这将是一个状态机:

public enum LeaveRequestState {

Submitted {
    @Override
    public LeaveRequestState nextState() {
        return Escalated;
    }

    @Override
    public String responsiblePerson() {
        return "Employee";
    }
},
Escalated {
    @Override
    public LeaveRequestState nextState() {
        return Approved;
    }

    @Override
    public String responsiblePerson() {
        return "Team Leader";
    }
},
Approved {
    @Override
    public LeaveRequestState nextState() {
        return this;
    }

    @Override
    public String responsiblePerson() {
        return "Department Manager";
    }
};

public abstract LeaveRequestState nextState(); 
public abstract String responsiblePerson();

}

现在您知道每个事件的下一个转换状态是什么。所以状态机非常关心状态实际实现的转换:

LeaveRequestState state = LeaveRequestState.Submitted;

state = state.nextState();
assertEquals(LeaveRequestState.Escalated, state);

state = state.nextState();
assertEquals(LeaveRequestState.Approved, state);

state = state.nextState();
assertEquals(LeaveRequestState.Approved, state);
于 2018-06-18T03:46:09.077 回答
2

状态机只是工作中的状态模式,或者这两者之间实际上存在差异

TL;DR:想象一下,您需要用行为不同的状态替换状态。然后想象你需要添加一个新的状态。

完整答案。有一个很大的不同。

状态模式抽象了状态并将它们彼此分离。因此,例如,您可以轻松地将一种特定状态替换为另一种状态。然而,当需要添加新状态和/或新转换时,您不会乐意重写所有状态。

状态机抽象状态图本身并将其与转换有效负载分离。要更改特定状态,您必须修复整个图表。但是要添加状态或转换,您只需要修复图表。

于 2017-05-08T20:04:09.027 回答
1

我写了一篇关于状态设计模式和状态机的文章:https ://medium.com/@1gravityllc/the-super-state-design-pattern-166127ce7c9a 。在文章中,我展示了它们的关注点不同,但它们也不是相互排斥的。有一种方法可以将两者结合起来,形成一种超状态设计模式

状态设计模式的重点在于封装行为以创建可重用、可维护的组件(状态)。

有限状态机的重点是状态及其转换(由状态图捕获),而不是实际行为(这是一个实现细节)。

本文描述了如何通过使用有限状态机来描述和管理对象的状态及其转换,从而将这两个概念结合起来,该对象使用状态设计模式将行为委托给状态对象。

于 2020-02-18T00:34:14.403 回答
0

看了这么多答案,我的理解是这样的:

  • 状态机是一个数学/工程术语。描述自动售货机或洗衣机等计算机的状态和状态转换的数学模型以状态图的形式呈现

  • 状态模式是编程的名称。设计模式是为了更好的规范代码设计结构,以便于封装、复用、易于扩展;状态模式用于解决对象根据状态表现出不同行为的问题

正确的关系是,如果需要开发一个“洗衣机”程序,产品经理应该画出状态图来描述状态机,然后交给程序员去实现。程序员可以通过多种方式实现此状态机,理想情况下是状态模式

于 2022-02-17T06:58:35.177 回答