Last Updated: 28.02.2026
The State Design Pattern is a type of Behavioral Design Pattern that allows an object to change its behavior when its internal state changes. The object will appear to change its class.
Instead of writing large if-else or switch statements based on state, we encapsulate each state into a separate class and delegate behavior to the current state object.
A traffic light behaves differently depending on its current state:
- Red → Stop
- Green → Go
- Yellow → Slow down
Instead of:
if(state == RED) { ... }
else if(state == GREEN) { ... }
else if(state == YELLOW) { ... }We create:
RedStateGreenStateYellowState
And the TrafficLight delegates behavior to the current state object.
You are building an e-commerce order system.
An order can be in the following states:
- CREATED
- PAID
- SHIPPED
- DELIVERED
- CANCELLED
Operations:
- pay()
- ship()
- deliver()
- cancel()
Rules:
- You cannot ship before payment.
- You cannot cancel after shipping.
- You cannot deliver before shipping.
- You cannot pay twice.
public class Order {
private String state; // "CREATED", "PAID", etc.
public void pay() {
if ("CREATED".equals(state)) {
state = "PAID";
} else {
throw new IllegalStateException("Cannot pay in state: " + state);
}
}
public void ship() {
if ("PAID".equals(state)) {
state = "SHIPPED";
} else {
throw new IllegalStateException("Cannot ship in state: " + state);
}
}
// More if-else everywhere...
}- ❌ Massive
if-elseblocks - ❌ Violates Open/Closed Principle
- ❌ Hard to add new states
- ❌ Hard to test
- ❌ Business logic tightly coupled
- ❌ High cyclomatic complexity
In interviews, this is called “State Explosion” problem.
| Component | Responsibility |
|---|---|
| Context | Maintains current state and delegates behavior |
| State (Interface) | Defines common behavior for all states |
| ConcreteState | Implements behavior for a particular state |
| State Transition Logic | Decides when to change state |
com.company.ordermanagement
├── context
│ └── Order.java
├── state
│ ├── OrderState.java
│ ├── CreatedState.java
│ ├── PaidState.java
│ ├── ShippedState.java
│ ├── DeliveredState.java
│ └── CancelledState.java
└── Main.java
package com.company.ordermanagement.state;
import com.company.ordermanagement.context.Order;
public interface OrderState {
void pay(Order order);
void ship(Order order);
void deliver(Order order);
void cancel(Order order);
String getName();
}package com.company.ordermanagement.context;
import com.company.ordermanagement.state.*;
public class Order {
private OrderState currentState;
public Order() {
this.currentState = new CreatedState();
}
public void setState(OrderState state) {
this.currentState = state;
}
public void pay() {
currentState.pay(this);
}
public void ship() {
currentState.ship(this);
}
public void deliver() {
currentState.deliver(this);
}
public void cancel() {
currentState.cancel(this);
}
public String getCurrentState() {
return currentState.getName();
}
}package com.company.ordermanagement.state;
import com.company.ordermanagement.context.Order;
public class CreatedState implements OrderState {
@Override
public void pay(Order order) {
order.setState(new PaidState());
}
@Override
public void ship(Order order) {
throw new IllegalStateException("Cannot ship before payment.");
}
@Override
public void deliver(Order order) {
throw new IllegalStateException("Cannot deliver before shipping.");
}
@Override
public void cancel(Order order) {
order.setState(new CancelledState());
}
@Override
public String getName() {
return "CREATED";
}
}public class PaidState implements OrderState {
@Override
public void pay(Order order) {
throw new IllegalStateException("Order already paid.");
}
@Override
public void ship(Order order) {
order.setState(new ShippedState());
}
@Override
public void deliver(Order order) {
throw new IllegalStateException("Cannot deliver before shipping.");
}
@Override
public void cancel(Order order) {
order.setState(new CancelledState());
}
@Override
public String getName() {
return "PAID";
}
}public class ShippedState implements OrderState {
@Override
public void pay(Order order) {
throw new IllegalStateException("Already paid.");
}
@Override
public void ship(Order order) {
throw new IllegalStateException("Already shipped.");
}
@Override
public void deliver(Order order) {
order.setState(new DeliveredState());
}
@Override
public void cancel(Order order) {
throw new IllegalStateException("Cannot cancel after shipping.");
}
@Override
public String getName() {
return "SHIPPED";
}
}Terminal states — all operations throw exceptions.
State pattern allows an object to change its behavior when its internal state changes by delegating state-specific behavior to separate classes.
- Eliminates conditional complexity
- Follows Open/Closed Principle
- Single Responsibility Principle
- ATM machines
- Media players (Play, Pause, Stop)
- Document workflow systems
- Order management systems
- TCP connection states
- Game character behavior
- Payment lifecycle
- Workflow engines
Example:
- Spring State Machine framework
- Workflow engines like Camunda
- When there are only 2 simple states
- When transitions are unlikely to grow
- When logic is trivial
- If simple enum + switch is enough
✔ Removes large conditionals ✔ Better maintainability ✔ Extensible ✔ Improves testability ✔ Follows SOLID
❌ More classes ❌ Slightly higher complexity ❌ Overkill for small systems
-
Difference between State and Strategy?
- Strategy = behavior chosen by client
- State = behavior changes internally
-
Can states share data?
- Yes, via context.
-
Who controls state transition?
- Usually ConcreteState.
-
How to make states reusable?
- Make them stateless + singleton.
Design an ATM machine
States:
- IdleState
- HasCardState
- AuthenticatedState
- DispensingCashState
Without state pattern → huge switch statements. With state pattern → each state controls allowed operations.
The State Pattern encapsulates varying behavior for the same object based on its internal state. It replaces conditional state logic with polymorphism by representing each state as a separate class and delegating behavior to the current state object.
If you want, next I can:
- Compare State vs Strategy vs Template Method
- Give you a low-level design interview question
- Or give you a machine coding round problem on State pattern 🚀