BEHAVIORAL PATTERNS / OBJECT DESIGN BRIEF

State pattern

The State pattern lets an object change its behavior when its internal state changes, as if it changed its class.

IntermediatePhase 06 / Topic 4 of 10ResponsibilitiesCollaborationsExtensibility
01

Overview

The State pattern lets an object change its behavior when its internal state changes, as if it changed its class. Each state is a separate class implementing the same interface; the context (a vending machine, an order, an elevator) delegates every request to its current state object, and states decide transitions.

It replaces large switch statements on a status field that appear in every method (if state == IDLE ... else if state == HAS_MONEY ...). With State, adding a new state means adding a class, and each state's rules are in one place. It is the standard implementation of a state diagram in LLD interviews.

A phone's modes

Pressing the power button does different things when the phone is locked, unlocked, or off. The button is the same; the current mode decides the behavior and which mode comes next.

02

When to use it

  • An object's behavior depends heavily on its current state.
  • Methods contain the same switch on a status field.
  • Machines and lifecycles: vending machine, ATM, elevator, order, traffic light, document workflow.
03

Where it shows up in interviews

Machine design

Recognize it when: device reacts differently to the same input by mode.

  • Design a vending machine
  • Design an ATM
  • Design an elevator system
Workflow lifecycles

Recognize it when: status with allowed transitions.

  • Design an order system
  • Design a document approval workflow
04

Where it is used in real software

TCP connection states

Classic example from the Gang of Four book: TCPConnection delegates to TCPEstablished, TCPListen, and TCPClosed.

Game character controllers

Idle, running, jumping, and attacking states handle input differently.

Workflow engines

Document approval and payment flows are modeled as state machines (Spring State Machine, XState).

05

Key terms

Context
The object whose behavior changes (VendingMachine).
State interface
Operations every state handles (insertCoin, select).
Concrete state
Behavior for one state (HasMoneyState).
Transition
A state setting the context's next state.
06

How it works, step by step

  1. 1
    Draw the state diagram

    States, events, transitions.

  2. 2
    Define the state interface

    One method per event.

  3. 3
    Implement a class per state

    Handle each event: act, transition, or reject.

  4. 4
    Context delegates

    machine.insertCoin() calls state.insertCoin(machine).

  5. 5
    States set the next state

    context.setState(new DispensingState()).

Vending machine with State pattern
Step 1 / 4
IdleState
HasMoneyState
DispensingState
SoldOutState

STEP 1Context delegates insertCoin(25) to IdleState, which adds credit and switches to HasMoneyState.

07

How each state handles events

Vending machine, item price 100

Step 1 / 4
StateinsertCoinselectcancel
IdleAdd credit, go HasMoneyReject: insert money firstNothing to refund
HasMoneyAdd creditIf credit >= 100: DispensingRefund, go Idle
DispensingReject: busyReject: busyReject: busy
SoldOutRefund immediatelyReject: sold outRefund

NOWState: Idle | insertCoin: Add credit, go HasMoney | select: Reject: insert money first | cancel: Nothing to refund

Each row is one class. No method in the machine contains a switch on state.

08

Implementation

public interface MachineState {    void insertCoin(VendingMachine m, int cents);    void select(VendingMachine m, String code);    void cancel(VendingMachine m);} public final class VendingMachine {    private MachineState state = new IdleState();    private int credit;    private final Map<String, Integer> prices = new HashMap<>();    private final Map<String, Integer> stock = new HashMap<>();     public void insertCoin(int cents) { state.insertCoin(this, cents); }    public void select(String code) { state.select(this, code); }    public void cancel() { state.cancel(this); }     void setState(MachineState s) { state = s; }    void addCredit(int c) { credit += c; }    int credit() { return credit; }    int refund() { int r = credit; credit = 0; return r; }    int price(String code) { return prices.getOrDefault(code, Integer.MAX_VALUE); }    boolean inStock(String code) { return stock.getOrDefault(code, 0) > 0; }    void dispense(String code) { stock.merge(code, -1, Integer::sum); credit -= price(code); }    boolean anyStock() { return stock.values().stream().anyMatch(q -> q > 0); }    public void load(String code, int price, int qty) { prices.put(code, price); stock.merge(code, qty, Integer::sum); }} final class IdleState implements MachineState {    public void insertCoin(VendingMachine m, int cents) { m.addCredit(cents); m.setState(new HasMoneyState()); }    public void select(VendingMachine m, String code) { System.out.println("Insert money first"); }    public void cancel(VendingMachine m) {}} final class HasMoneyState implements MachineState {    public void insertCoin(VendingMachine m, int cents) { m.addCredit(cents); }    public void select(VendingMachine m, String code) {        if (!m.inStock(code)) { System.out.println("Item unavailable"); return; }        if (m.credit() < m.price(code)) { System.out.println("Price: " + m.price(code)); return; }        m.dispense(code);        System.out.println("Dispensed " + code + ", change " + m.refund());        m.setState(m.anyStock() ? new IdleState() : new SoldOutState());    }    public void cancel(VendingMachine m) { System.out.println("Refund " + m.refund()); m.setState(new IdleState()); }} final class SoldOutState implements MachineState {    public void insertCoin(VendingMachine m, int cents) { System.out.println("Sold out, returning " + cents); }    public void select(VendingMachine m, String code) { System.out.println("Sold out"); }    public void cancel(VendingMachine m) {}}
09

Complexity and performance

Event handlingO(1) dispatch

Delegation to current state.

Classes1 per state

Plus interface and context.

10

Trade-offs

Classes vs a transition table

For simple transitions with little behavior, an enum table is shorter; State shines when behavior per state differs a lot.

Who owns transitions

States deciding transitions spreads the diagram across classes; a central table keeps it visible.

11

Variants and related techniques

State vs Strategy

Same structure; strategies are chosen by clients, states switch themselves as events occur.

Enum-based states

Java enums with abstract methods implement small state machines compactly.

Singleton states

Stateless state objects can be shared instances.

12

Common mistakes

  • Keeping state data inside state objects that get replaced.

    Fix: Keep shared data (credit, stock) in the context; states hold behavior.

  • Forgetting invalid events.

    Fix: Every state must handle every event explicitly (reject or ignore).

13

Interview questions

How does the State pattern differ from Strategy?

Both delegate to an interface. With Strategy, the client selects the algorithm and it rarely changes. With State, the object moves between states itself as events happen, and each state determines the next.

Why use State instead of a switch on status?

A switch repeated in every method grows with each new state and mixes all rules together. State puts each state's behavior and transitions in its own class, following SRP and OCP.

14

Practice problems

ProblemDifficultyWhat it trains
Traffic light with pedestrian buttonEasyTimed transitions.
Vending machine with State patternMediumEvents and refunds.
ATM session states (card, PIN, transaction)MediumSecurity rules.