State Design Pattern Explained
State lets an object alter its behavior when its internal state changes, appearing to change its class.
Published November 13, 2026
The State pattern lets an object change its behaviour when its internal state changes, by delegating to separate state objects instead of using large conditionals.
The concept
Each state is a class implementing the same methods. The context holds a current state and forwards calls to it; states can switch the context to another state.
Typical examples: order status (pending, paid, shipped), traffic lights, media players, TCP connections.
Order lifecycle
- Pending: can pay or cancel
- Paid: can ship or refund
- Shipped: can only mark delivered
- Delivered: final
Practical examples
State objects
const states = {
pending: { pay: (o) => (o.state = 'paid'), ship: () => { throw new Error('pay first') } },
paid: { pay: () => {}, ship: (o) => (o.state = 'shipped') },
shipped: { pay: () => {}, ship: () => {} },
}
class Order { state = 'pending'
pay() { states[this.state].pay(this) }
ship() { states[this.state].ship(this) } }Instead of this
if (status === 'pending') {...} else if (status === 'paid') {...}Enforce transitions
const next = { pending: ['paid'], paid: ['shipped'], shipped: ['delivered'] }Common mistakes
- Allowing illegal transitions.
- Duplicating shared behaviour in every state.
- Using it for just two states.
Key takeaways
- Behaviour depends on state objects.
- Removes big conditionals.
- Define legal transitions.
FAQ
State vs Strategy?
State changes itself over time; Strategy is chosen by the caller.
What is a state machine?
A formal model of states and transitions, implemented with this pattern.