To allow an object to change its behavior when the state of the object changes. When the object changes behavior it will appear to change class.
When to use it
State should be used when:
- An object needs to change its behavior during runtime depending on the state it is in. (Anything that can be modeled as a state machine)
- Your code has groups of nested conditionals that provide different behavior depending on the state of the object.
How it works
One abstract State class is introduced containing the common interface for all the states. Every different behavior is represented as a new subclass of this State class.
The object needing the state behavior creates and initalises one instance of each state and uses a common reference to point to the current state. Now the object can access the appropriate behavior through the common interface of the State class.
This class will be called by clients and provides methods of interest to them. It also holds a ConcreteState applicable to the current state and passes on state-specific requests to the current ConcreteState.
This class defines an interface for the behavior associated with a particular state.
Each ConcreteState implements the behavior applicable to a particular object state.
Either ConcreteState or the Context may decide which states follow which other states and under what circumstances.
- State-specific behavior for one state is pulled out into one object and is separated from behavior for other states. However, this greatly increases the number of classes.
- State transitions are made explicit. This means that the Context cannot get into an inconsistent state because state transitions are atomic.
- State object can be easily shared to reduce the number of objects in a system.
A very common example where you almost have to (?) use this pattern is when going through different states of your program. For instance, a level editor for a game could have the following states:
- Display level and let user move items around
- Add a new item
- Add a special item (like 'drawing' a road or track)
Each state has methods like DrawLevel(), OnKeyboardEvent(), and OnMouseEvent(). This supports beware type switches.
You can find here a nicely explained java code example of the State Pattern usage in the real world.
- Flyweight: This pattern may be used to share State objects.
- Singleton: Often, only a single instance of each ConcreteState is required. In that case, they may be implemented as Singletons.
- Strategy & Bridge: The state pattern is almost identical in structure to both Strategy and Bridge patterns but the intents for each differ. The Strategy vs State vs Bridge section here is a must see.
Creational: Abstract Factory | Builder | Factory Method | Prototype | Singleton