开发者

State pattern: why states are not Singletons?

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?


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.


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


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜