I think you are perhaps limiting yourself to thinking only in terms of the objects implementing the state pattern (Context object and State objects). This is not the case, and there is other objects involved (Clients). It is possible, that the client, which holds a reference to the context object, should have the responsibility of transitioning state.
Consider this made up example:
// Paintbrush is the context object
class Paintbrush {
// The State object, ColourState would be the abstraction
private ColourState colourState;
// ... other class stuff
public paint() {
// Delegation to the state object
this.colourState.paintInYourSpecificColour();
}
public void setColourState(ColourState newState) {
this.colourState = newState;
}
}
This should be enough implementation for the context object. Note that neither colourState
nor the Paintbrush
class have any knowledge of state transitions. This is to reduce the number of responsibilities, as well as to provide a more flexible design.
Basically, changes of state could be the responsibility for the calling class. How this is actually achieved in code is implementation detail, but the important thing to note is that neither the context object nor the state object have a responsibility for transitioning state.
I'm trying to make sure I don't use a Strawman argument, but I'll continue to run with the example. Say at different points you wanted to paint different patterns, and the colours used must be in a specific order, your client would decide when to change state, like this:
public void paintRainbow() {
paintbrush.setColourState(new RedColourState());
// do painting...
// Change state to next colour
paintbrush.setColourState(new OrangeColourState());
// Chane state again, and so on...
}
You could have the order of colours specified by the state or the context object, ie. have a subclass of Paintbrush
called RainbowPaintbrush
, and it would pick the next colour. Or your state objects could pick the next state, in which case you would have to have a RedRainbowColourState
, which knew the next state was OrangeRainbowColourState
and so on. But the problem with both these examples is that you have to go in and modify (by extension) both the context and the state objects to achieve a different set of transitions. However, if neither know the transitions, and that is the responsibility of the calling class, this can be done without changing the state or context object. Ie.
public void paintChessboard() {
paintbrush.setColourState(blackColourState);
// do painting...
// change state
paintbrush.setColourState(whiteColourState);
// etc...
}
This is a simplified example, but it generally holds.
A quick read of Wikipedia's example of the State pattern shows that individual states have knowledge of the next state, so I don't think it's invalid do so. I guess overall it's a tradeoff of where you want the control to be, and how that will fit into your problem. This is how using the concrete state objects to transition would fit into my lame example:
public class RedRainbowColourState implements ColourState {
public void doPaint(Paintbrush paintbrush) {
// do painting
ColourState nextStateInRainbow = new OrangePaintbrushColourState();
paintbrush.setColourState(nextStateInRainbow);
}
But note the explosion of state classes that will be required to transition through all the states using this way. However, an advantage here is that the client can be relieved of responsibility and knowledge of how to create the individual states. In your situation, that may be better way to transition.
To summarise, you can let the individual states perform the transition, or even the context object. Another choice is to let the client handle state transitions.