1

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

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

4

5 回答 5

10

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

看一下您引用的 Wikipedia 示例:

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 中,您可能希望每个状态都是幂等的(后续调用给出相同的反馈),但状态模式更通用。维基百科页面上描述的一种目标用途是:

对象在运行时部分更改其类型的干净方法

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

于 2010-06-22T07:07:05.213 回答
1

假设你的对象有一个状态。现在,如果您需要“只需要一个完整的类似的东西”怎么办?

于 2010-06-22T07:05:31.660 回答
1

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

如果每个州都是单身人士,这是不可能的。

于 2010-06-22T07:06:20.520 回答
1

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

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

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可以访问状态,所以它们不是单例。这是享元模式的经典示例。

于 2010-06-22T20:21:02.503 回答
0

应该反过来问这个问题:为什么要State单身?仅当您需要全局访问并且拥有多个实例时才需要单例。

拥有多个 a 实例当然不是错误State,而且您也不需要全局访问,因此无需将它们设为单例。

于 2010-06-22T07:12:03.063 回答