State and Strategy patterns are structurally almost identical. How do they differ, and how do you decide which one you're using?
answer
- Same UML, different intent
- Strategy = which algorithm; State = which mode/lifecycle
- Strategy set by client (often once); State swapped by the object itself
- States know each other and transition; strategies are mutually ignorant
- State = a state machine over time
basics
~20 sThey look the same — both delegate to a swappable object behind an interface. The difference is intent: Strategy is an algorithm the client picks and usually keeps fixed; State is a mode the object switches between itself as conditions change, with the states often driving the transitions.
solid answer
~50 sState and Strategy share the same structure: a context holds a reference to an interchangeable object behind a common interface and delegates to it. The difference is intent. Strategy encapsulates interchangeable algorithms for *how* to do one thing — sorting, pricing, compression — typically chosen by the client, set once, and unaware of each other. State encapsulates *what* an object can do in each mode of its lifecycle; the context transitions between states over time, and the states usually know about and trigger transitions to one another, forming a state machine. A practical tell: if the swapping is driven externally and the implementations are mutually ignorant and stable, it's Strategy. If the object changes its own behavior as its internal condition evolves and the variants reference each other to move forward, it's State. They're the same code skeleton solving different problems — Strategy is about pluggable behavior, State is about lifecycle-driven behavior.
code
java · 14 lines// STRATEGY: client picks an interchangeable algorithm, variants ignore each other
interface PricingStrategy { double price(double base); }
class RegularPricing implements PricingStrategy { public double price(double b){ return b; } }
class HolidayPricing implements PricingStrategy { public double price(double b){ return b*0.8; } }
class Checkout { private PricingStrategy s; Checkout(PricingStrategy s){ this.s = s; } }
// STATE: the object transitions between mutually-aware modes over time
interface OrderState { OrderState pay(); OrderState ship(); }
class New implements OrderState { public OrderState pay(){ return new Paid(); }
public OrderState ship(){ throw new IllegalStateException(); } }
class Paid implements OrderState { public OrderState pay(){ throw new IllegalStateException(); }
public OrderState ship(){ return new Shipped(); } }
class Shipped implements OrderState { public OrderState pay(){ throw new IllegalStateException(); }
public OrderState ship(){ throw new IllegalStateException(); } }go deeper
Can state that both swap an object behind an interface and that 'one is about algorithms, the other about modes'.
Explains the intent difference and gives a correct example of each (Comparator vs. connection open/closed).
Uses the decisive tells (who drives the swap, do variants transition, is there a lifecycle) and frames State as a state machine.
Articulates that patterns name intent not structure, discusses evolution paths, hybrids, and when to drop the formal pattern for an enum or table-driven machine.
## Why this question exists In the Gang of Four catalog, **State** and **Strategy** have nearly identical UML diagrams: a **context** holds a reference to an object implementing a common **interface**, and delegates work to it. Because the *structure* is the same, the patterns are distinguished only by **intent** — and interviewers love probing whether you understand that patterns are about purpose, not just shape. ## Quick definitions - **Strategy** is a behavioral pattern that defines a family of **interchangeable algorithms**, encapsulates each one, and makes them swappable. It lets the algorithm vary independently of the clients that use it. Classic uses: different sort orders, pricing rules, compression methods, payment processors. - **State** is a behavioral pattern that lets an object **alter its behavior when its internal state changes**, so it appears to change its class. Classic uses: connection open/closed, document workflow (draft/review/published), TCP connection states, vending machines. ## The structural twins Both have: ``` Context --has-a--> Interface <--implemented by-- ConcreteA, ConcreteB, ... ``` The context calls `interface.doIt()` and the concrete object supplies the behavior. If you only looked at the class diagram, you couldn't tell them apart. That's the whole point of the comparison. ## How intent diverges | Dimension | **Strategy** | **State** | |---|---|---| | What varies | *How* a single task is done (the algorithm) | *What* the object does across its lifecycle (its mode) | | Who sets the variant | Usually the **client**, often once at construction | The object **itself**, repeatedly, as conditions change | | Do variants know each other? | **No** — strategies are independent and ignorant of siblings | **Often yes** — states know their successors and trigger transitions | | Lifetime | Typically fixed for the operation | Changes over time = a **state machine** | | Mental model | "Pick a plug-in." | "Walk a lifecycle." | ## The decisive tells 1. **Who drives the swap?** If an *external* client chooses and the choice is stable, it leans Strategy. If the *object* swaps its own behavior as its internal condition evolves, it's State. 2. **Do the variants reference each other?** Strategies are mutually unaware. States frequently say `context.setState(new NextState())` — they form a graph of transitions. The presence of *transitions between variants* is the strongest signal of State. 3. **Is there a lifecycle?** State implies the object moves through a sequence of modes over time. Strategy implies a single point-in-time choice of algorithm. 4. **What's the question being answered?** Strategy answers "*which algorithm?*"; State answers "*what am I allowed/expected to do right now?*" ## Java framing In modern Java both are often expressed with a **sealed interface** plus `record`/class implementations, or with an `enum` (Java enums can give each constant its own method body, which is a neat fit for small fixed state machines or strategy sets). A `Comparator` passed to `sort` is Strategy. A driver's open/closed handling inside a `Connection` is State. The JVM and standard library use both heavily; `java.util.Comparator`, `ThreadPoolExecutor`'s `RejectedExecutionHandler`, and layout managers are Strategy; thread lifecycle and connection lifecycle are State-shaped. ## Why it doesn't matter that they share code Design patterns are vocabulary for *intent*. Two patterns can compile to the same skeleton and still be different design decisions, because naming the intent tells the next reader *why* the indirection exists and *how it will evolve* — Strategy by adding independent algorithms, State by adding nodes/edges to a machine. Picking the right name is documentation, not mechanics. ## Edge cases / nuance - A Strategy *can* change at runtime (e.g. adaptive algorithm selection) — that alone doesn't make it State. The differentiator is whether there's a *lifecycle with transitions between mutually-aware variants*. - Some designs are genuinely hybrid; don't over-police the label. The value is communicating intent, not winning a taxonomy debate.
- A Comparator passed to Collections.sort — is that State or Strategy, and why?Strategy. The comparator is an interchangeable algorithm for 'how to order', chosen by the client, fixed for the sort, and unaware of other comparators. There's no lifecycle and no transition between comparators, so none of the State signals apply.
- If a Strategy can be swapped at runtime, doesn't that make it State?Not by itself. Runtime swapping is allowed for both. State is distinguished by an object progressing through a lifecycle where the variants are mutually aware and trigger transitions. A strategy chosen adaptively is still answering 'which algorithm', not 'what mode am I in'.
saying these in an interview costs you the question
- Saying they differ structurally — they are essentially the same UML; the difference is intent.
- Claiming State variants must be unaware of each other — it's usually the opposite; they often drive transitions.
- Asserting Strategy can never change at runtime — it can; that's not the distinguishing factor.
- Treating the labels as a strict, mutually exclusive taxonomy rather than a communication of intent.