1. Definition
The State pattern is a behavioral design pattern that allows an object to change its behavior when its internal state changes, as if the object changed its class.
2. Problem Statement
Imagine an object that has multiple operational modes, and its behavior changes based on the current mode. If we use conditional statements to manage these behaviors, it can make the code complex, hard to manage, and difficult to extend.
3. Solution
The State pattern suggests creating individual state classes for each state of the object, and to extract all state-specific behaviors into these classes. Instead of implementing all behaviors on its own, the context stores a reference to one of the state objects and delegates all the state-related work to this object.
4. Real-World Use Cases
1. A vending machine that has different states such as “idle”, “dispensing product”, “out of stock”, and “awaiting payment”.
2. Media players that can have states like “playing”, “paused”, “stopped”, etc.
5. Implementation Steps
1. Declare the state interface.
2. Implement concrete state classes for all possible states.
3. In the context class, maintain a reference to the current state and delegate state-specific tasks to the current state object.
6. Implementation in Java
// State Interface
interface State {
void handleRequest();
}
// Concrete State 1
class StateA implements State {
@Override
public void handleRequest() {
System.out.println("Handling request by StateA");
}
}
// Concrete State 2
class StateB implements State {
@Override
public void handleRequest() {
System.out.println("Handling request by StateB");
}
}
// Context
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handleRequest();
}
}
// Client Code
public class Client {
public static void main(String[] args) {
Context context = new Context(new StateA());
context.request();
context.setState(new StateB());
context.request();
}
}
Output:
Handling request by StateA Handling request by StateB
Explanation:
The StateA and StateB classes implement the State interface, defining behaviors specific to each state. The Context class has a reference to a State object, which represents its current state. Rather than implementing state-specific behaviors on its own, the context delegates the work to the current state object. In the client code, we demonstrate how the behavior of the Context changes when its state changes.
7. When to use?
1. When an object’s behavior varies depending on its state, and it must change its behavior at runtime depending on that state.
2. When operations have large, multi-part conditional statements that depend on the object’s state. This state is often represented by one or several enum constants.