State
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
Intent
Encapsulate state-specific behavior into separate state objects and delegate behavior to the current state, so the host object changes its behavior dynamically as its state transitions without resorting to large conditional blocks.
Problem
An object must change its behavior based on its internal state, and the number of states keeps growing. The code becomes riddled with conditionals that check the current state before every operation, making it fragile and difficult to add new states without touching existing logic.
Solution
Create a State interface that declares the methods whose behavior varies by state. Implement a ConcreteState class for each distinct state. The Context holds a reference to the current state object and delegates state-dependent work to it. State transitions are performed by swapping the current state object, either by the Context or by the state objects themselves.
Participants
- State — defines an interface for encapsulating the behavior associated with a particular state of the Context
- ConcreteState — each subclass implements behavior associated with a state of the Context
- Context — maintains a reference to the current ConcreteState and delegates state-specific behavior to it
Advantages
- Localizes state-specific behavior and partitions behavior for different states into separate classes
- Makes state transitions explicit by replacing conditional logic with polymorphic dispatch
- New states can be added without modifying the Context or other state classes
- Eliminates monolithic conditionals that test the current state across multiple operations
Disadvantages
- Increases the number of classes, which can feel heavy for objects with few states
- State objects may need access to Context internals, which can tighten coupling
- If state transitions are scattered across concrete states, the overall flow can be hard to follow
Real-World Analogy
Think of a traffic light. It cycles through three states — green, yellow, and red — and its behavior (whether cars stop, slow, or go) depends entirely on the current state. Each state knows how long it lasts and which state comes next. The traffic light itself does not contain a giant if-else block; instead, the current light phase dictates the behavior.
Use Cases
- Order lifecycle management — draft, submitted, paid, shipped, delivered, cancelled
- Document workflow — draft, review, approved, published, archived
- Media player controls — stopped, playing, paused
- TCP connection states — listen, established, closed
- Vending machine operations — idle, accepting coins, dispensing, out of stock
- Game character states — idle, walking, running, jumping, attacking
Code Examples
A document workflow where the Document delegates edit, submit, approve, and reject actions to its current state object. Each state controls which transitions are allowed.