Behavioral Patternshigh

State Machine / State Pattern

Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. State-specific behavior is encapsulated in separate State classes.

Memory anchor

State = a vending machine. Insert coin and it changes personality: from 'insert coin please' mode to 'pick your snack' mode. Same machine, totally different behavior depending on what state it's in. Each state is a different mood.

Expected depth

Context holds a reference to a State interface. When an event occurs, the context delegates to the current state. The state handles the event (and may transition the context to a new state). This eliminates if-else or switch chains on state flags. Classic examples: vending machine states (idle, coin-inserted, dispensing, out-of-stock); traffic light (red/yellow/green with time-based transitions); order lifecycle (pending, paid, shipped, delivered, cancelled).

Deep — senior internals

State vs Strategy: structurally identical — both have a Context delegating to an interface. The difference: in Strategy, the context does not change its strategy during normal operation (it is injected once); in State, the state changes during operation as part of the state machine's transitions. Who owns transitions? In GoF State, the concrete states set the next state on the context (state-driven transitions); alternatively, a transition table in the context maps (currentState, event) → nextState (table-driven transitions). Table-driven is more declarative and easier to extend but requires the state machine to be aware of all transitions. For complex state machines, consider a dedicated state machine library (Spring State Machine, XState) — they provide visual modeling, persistence, and history states.

🎤Interview-ready answer

State is the pattern for objects whose behavior changes dramatically based on internal state. For an Order object: rather than if (status == PENDING) doX() else if (status == PAID) doY(), I have a State interface with ship(), cancel(), refund() methods. PendingState, PaidState, ShippedState each implement the interface — PendingState.cancel() transitions to CancelledState; PaidState.cancel() triggers a refund first. The Order context delegates all lifecycle methods to its current state. Adding a new state (BackorderedState) is a new class, not a change to Order. I always discuss who owns transitions and mention the state machine framework option for complex lifecycles.

Common trap

For simple two- or three-state objects with minimal transition logic, State is over-engineering. The pattern earns its complexity when states are 5+, transition logic is non-trivial, or state-specific behaviour spans many methods.

Related concepts