代码之家  ›  专栏  ›  技术社区  ›  MarcoS

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

  •  1
  • MarcoS  · 技术社区  · 14 年前

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

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

    5 回复  |  直到 8 年前
        1
  •  10
  •   Matt Mitchell    14 年前

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

    看看你引用的维基百科例子:

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

    一个干净的方法 运行时部分更改其类型

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

        2
  •  1
  •   Pavel Radzivilovsky    14 年前

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

        3
  •  1
  •   Andreas Dolk    14 年前

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

    如果每个州都是一个单独的州,这是不可能的。

        4
  •  1
  •   munificent    14 年前

    如果您的状态不需要特定于机器的附加状态数据,那么在多台机器之间重用它们是非常有意义的。那 意味着他们是单身汉:单身汉也意味着 全局访问 你几乎不想要。

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

    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 存在实例。同时,除了 光开关 有权进入美国,所以他们不是单身汉。这是Flyweight图案的经典示例。

        5
  •  0
  •   Dean Harding    14 年前

    问题应该反过来问:为什么 State 作为单身汉?只有当你 要求 全球访问,它是一个 错误 拥有多个实例。

    当然不是 错误 拥有一个以上的 状态 你也没有 要求 全球接入,所以没有必要让它们成为单件。