The State Pattern: When Your Object's Behavior Depends on Its Mode

2026-05-07

If you've ever written a class with a status field and a growing thicket of if (status == "X") branches inside every method, you've felt the pain the State pattern solves. The pattern says: instead of one object that checks its mode on every call, give each mode its own class and delegate behavior to the current state object.

The smell. A typical Order class:

Every new status forces edits across every method. Every new method forces you to think about every status. That's an O(states × actions) maintenance burden.

The pattern. Define a OrderState interface with the actions (ship, cancel, refund). Implement PendingState, PaidState, ShippedState, DeliveredState, CancelledState. The Order holds a reference to its current state and delegates: order.ship() just calls currentState.ship(this). Each state decides what's legal and which state to transition to next. Illegal transitions throw from the state, not from a giant switch.

Real example. A document workflow: Draft → InReview → Approved → Published → Archived. In DraftState.submit(), you transition to InReviewState. In PublishedState.submit(), you throw — you can't submit something already live. Adding a new RejectedState? Create one class, wire it into the two states that transition to it. No existing methods change.

Rule of thumb. Reach for State when you have 3+ statuses and 3+ methods that branch on status. Below that threshold, conditionals are fine — the pattern's overhead (a class per state, a transition map) isn't worth it. A 5×5 matrix means 25 conditional branches scattered across methods; five state classes with five methods each is the same code, but each state's rules sit in one file.

Watch out for:

State pattern vs. Strategy: same shape, different intent. Strategy swaps algorithms by client choice; State swaps behavior because the object's lifecycle changed.

See it in action: Check out Vibration Experiment: Dust Forms Patterns Instantly On Platform by fanghang lu2 to see this theory applied.
Key Takeaway: When status-based conditionals multiply across methods, replace them with state classes that own their own transition rules.

All newsletters