状态模式:为什么状态不是单例?

发布于 2024-09-06 12:53:12 字数 259 浏览 5 评论 0原文

我使用状态模式来实现一个简单的有限状态机。看看 Wikipedia 上给出的描述,更具体地说是建议的 Java 实现,我想知道为什么实现 State 接口的类(即各种状态)不是单例吗?

在建议的实现中,每当发生转换时就会创建一个新的状态。然而,一个对象足以代表每种状态。那么,为什么每次发生转换时都要浪费时间创建新实例呢?

I've used the State pattern to implement a simple finite state machine. Looking at the description given on Wikipedia, and more specifically at the suggested Java implementation, I wondered why classes implementing the State interface (i.e. the various states) are not Singletons?

In the suggested implementation a new State is created whenever a transition occurs. However, one object is sufficient to represent each state. So, why wasting time creating a new instance every time a transition occurs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

冷默言语 2024-09-13 12:53:12

因为每个状态都可以存储实例变量?

看一下您引用的维基百科示例:

class StateB implements State { 
    private int count=0; 
    public void writeName(StateContext stateContext, String name) { 
        System.out.println(name.toUpperCase()); 
        if(++count>1) { 
            stateContext.setState(new StateA()); 
        }
    }
}

您能看到它如何存储输入次数的计数吗?

现在,在 FSM 中,您可能希望每个状态都是幂等(后续调用会给出相同的反馈)但状态模式更为通用。维基百科页面上描述的一种目标用途是:

一种让对象干净的方式
在运行时部分更改其类型

由于大多数对象在执行操作时可能会使用其局部变量,因此您可能希望“更改类型”版本也使用局部变量。

Because each state can store instance variables?

Take a look at the Wikipedia example you reference:

class StateB implements State { 
    private int count=0; 
    public void writeName(StateContext stateContext, String name) { 
        System.out.println(name.toUpperCase()); 
        if(++count>1) { 
            stateContext.setState(new StateA()); 
        }
    }
}

Can you see how it stores a count of the number of times it has been entered?

Now, in a FSM you probably want each state to be idempotent (subsequent calls give the same feedback) but the State pattern is more general. One target use as described on the wikipedia page is:

A clean way for an object to
partially change its type at runtime

As most objects probably use their local variables when performing actions, you would want the "changed type" version to use local variables as well.

尘曦 2024-09-13 12:53:12

假设你的对象有一个状态。现在,如果您需要“再做一件这样的事情”怎么办?

Assume your object has a state. Now what if you need "just one more whole thing like that"?

-黛色若梦 2024-09-13 12:53:12

您可能需要一个“有状态的状态”对象(如一个示例所示)参考维基百科页面),此外,您可能希望在同一个 JVM 中运行多个相同类型的状态机。

如果每个州都是单例的话,这是不可能的。

You may want a 'stateful-State' object (like demonstrated as one example on the references wikipedia page) and in addition you may want to run several state machines of the same type in the same JVM.

This wouldn't be possible if each State was a Singleton.

故事和酒 2024-09-13 12:53:12

如果您的状态不需要特定于机器的附加状态数据,那么跨机器重用它们是非常有意义的。这并不意味着它们是单例:单例还意味着全局访问,而这是你几乎永远不想要的。

这是一个简单的状态机,它重用状态,但不会使它们成为单例。

public class SwitchState
{
    public SwitchState(bool isOn)
    {
        mIsOn = isOn;
    }

    public void InitToggleState(SwitchState state)
    {
        mToggleState = toggleState;
    }

    public bool IsOn { get { return mIsOn; } }
    public SwitchState Toggle() { return mToggleState; }

    private SwitchState mToggleState;
    private bool mIsOn;
}

public class LightSwitch
{
    public LightSwitch()
    {
        mState = sOnState;
    }

    public bool IsOn { get { return mState.IsOn; } }

    public void Toggle()
    {
        mState = mState.Toggle();
    }

    static LightSwitch()
    {
        sOnState = new SwitchState(true);
        sOffState = new SwitchState(false);

        sOnState.InitToggleState(sOffState);
        sOffState.InitToggleState(sOnState);
    }

    private static SwitchState sOnState;
    private static SwitchState sOffState;

    private SwitchState mState;
}

您可以看到,无论有多少个 LightSwitch 实例,整个应用程序中都只有一个打开和关闭状态。同时,LightSwitch 之外的任何内容都无法访问状态,因此它们不是单例。这是享元模式的经典示例。

If your states don't need machine-specific additional state data, it makes perfect sense to reuse them across machines. That doesn't mean they are Singletons: Singletons also imply global access which you almost never want.

Here's a simple state machine that reuses states, but doesn't make them singletons.

public class SwitchState
{
    public SwitchState(bool isOn)
    {
        mIsOn = isOn;
    }

    public void InitToggleState(SwitchState state)
    {
        mToggleState = toggleState;
    }

    public bool IsOn { get { return mIsOn; } }
    public SwitchState Toggle() { return mToggleState; }

    private SwitchState mToggleState;
    private bool mIsOn;
}

public class LightSwitch
{
    public LightSwitch()
    {
        mState = sOnState;
    }

    public bool IsOn { get { return mState.IsOn; } }

    public void Toggle()
    {
        mState = mState.Toggle();
    }

    static LightSwitch()
    {
        sOnState = new SwitchState(true);
        sOffState = new SwitchState(false);

        sOnState.InitToggleState(sOffState);
        sOffState.InitToggleState(sOnState);
    }

    private static SwitchState sOnState;
    private static SwitchState sOffState;

    private SwitchState mState;
}

You can see there will only be a single on and off state in the entire application regardless of how many LightSwitch instances there are. At the same time, nothing outside of LightSwitch has access to the states, so they aren't singletons. This is a classic example of the Flyweight pattern.

你的他你的她 2024-09-13 12:53:12

这个问题应该以相反的方式问:为什么将 State 作为单例?仅当您需要全局访问并且拥有多个实例时错误时才需要单例。

拥有多个 State 实例当然不是一个错误,而且您也不需要需要全局访问权限,因此没有必要让他们成为单身人士。

The question should be asked the other way around: why have State as a singleton? A singleton is only needed when you require global access and it is an error to have more than one instance.

It's certainly not an error to have more than one instance of a State, and you also do not require global access, so there is no need to make them singletons.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文