State Design Pattern
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. (dofactory)
- Context defines the interface of interest to clients and maintains an instance of a ConcreteState subclass that defines the current state.
- State defines an interface for encapsulating the behavior associated with a particular state of the Context.
- Each ConcreteSate implements a behavior associated with a state of Context.
- Context delegates state-specific requests to the current ConcreteState object.
- A context may pass itself as an argument to the State object handling the request. This lets the State object access the context if necessary.
- Context is the primary interface for clients. Clients can configure a context with State objects. Once a context is configured, its clients don't have to deal with the State objects directly.
- Either Context or the ConcreteState sub-classes can decide which state succeeds another and under what circumstances.
- The State pattern does not specify where the state transitions will be defined. The choices are two: the Context object, or each individual ConcreteState sub-class. The advantage of the latter option is ease of adding new ConcreteState sub-classes. The disadvantage is each ConcreteState sub-class has knowledge of (coupling to) its siblings, which introduces dependencies between sub-classes.
- A table-driven approach to designing finite state machines does a good job of specifying state transitions, but it is difficult to add actions to accompany the state transitions. The pattern-based approach uses code (instead of data structures) to specify state transitions, but it does a good job of accommodating state transition actions.
- When the behavior of an object should be influenced by it's state.
- When complex conditions tie object behavior to it's state.
- Removes conditional (if/else/switch) statements relating to different states check.
- Increases cohesion by aggregating state specific behavior into ConcreteState sub-classes with intention revealing names it’s easier to find that specific logic, and it’s all in one place.
- Easy to add new states
- Helps us in using the Single Responsibility Principle (SRP).
- Each ConcreteState sub-class has knowledge of (coupling to) its siblings, which introduces dependencies between sub-classes.
- State pattern could be very verbose, when there are many states.
- Some operations may not be possible when the context is in certain states (However, see this article for solution)
- Strategy has two different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).
- The implementation of the State pattern builds on the Strategy pattern. The difference between State and Strategy is in the intent. With Strategy, the choice of algorithm is fairly stable. With State, a change in the state of the “context” object causes it to select from its “palette” of Strategy objects.
- The structure of State and Bridge are identical (except that Bridge admits hierarchies of envelope classes, whereas State allows only one). The two patterns use the same structure to solve different problems: State allows an object’s behavior to change along with its state, while Bridge’s intent is to decouple an abstraction from its implementation so that the two can vary independently.
- Flyweight explains when and how State objects can be shared.
- Interpreter can use State to define parsing contexts.