# Java Design Patterns: Strategy vs. State – Key Differences Explained

> Understand the core differences between Java Strategy and State design patterns. Learn when to use each to manage interchangeable algorithms and object behavior transitions effectively.

- Repository: [CyC2018/CS-Notes](https://github.com/CyC2018/CS-Notes)
- Tags: deep-dive
- Published: 2026-02-24

---

**The Strategy pattern encapsulates interchangeable algorithms selected explicitly by the client, while the State pattern manages internal behavioral transitions where the object appears to change its class based on lifecycle conditions.**

Understanding the distinction between **Strategy** and **State** is essential for applying behavioral patterns correctly in Java. According to the source code in the [CyC2018/CS-Notes](https://github.com/CyC2018/CS-Notes) repository, both patterns use delegation but solve fundamentally different architectural problems—Strategy handles algorithmic variation, while State manages complex object lifecycle transitions. This article breaks down the structural differences, control flow mechanisms, and practical implementations found in `notes/设计模式 - 策略.md` and `notes/设计模式 - 状态.md`.

## Core Conceptual Differences

### Purpose and Intent

**Strategy** addresses the need to encapsulate a family of interchangeable **algorithms** and let the client pick or switch one at runtime. The pattern defines a `Strategy` interface and multiple concrete implementations (such as different sorting or validation algorithms) that the context can use interchangeably.

**State** allows an object to change its **behavior** when its internal **state** changes, making the object appear to change its class. Rather than selecting algorithms externally, the pattern models an object that passes through distinct phases (like `NoQuarterState` to `HasQuarterState` in a vending machine), with each phase defining its own behavior and transition rules.

### Control Flow and Transition Triggers

In the **Strategy** pattern, the client explicitly controls which algorithm executes. The client code calls `context.setStrategy(new ConcreteStrategy())`, and the context simply forwards requests to the current strategy instance. This represents a *static* composition where the set of algorithms is defined once, and external code decides which to use.

In the **State** pattern, state transitions happen *internally*. Concrete state classes (like `NoQuarterState`) hold a reference back to the context (e.g., `private GumballMachine gumballMachine`) and trigger transitions by calling `machine.setState(machine.getHasQuarterState())` within their own methods. This creates a *dynamic* composition driven by the object's internal state machine rather than external client decisions.

### Coupling and Object Relationships

**Strategy** maintains loose coupling: the context knows only the `Strategy` interface, and concrete strategies remain independent of the context. They receive data through method parameters rather than holding references to the context.

**State** introduces tighter coupling between concrete states and the context. Because states must trigger transitions (e.g., moving from `HasQuarterState` to `SoldState` when the crank turns), concrete state classes typically maintain a back-reference to the context object, allowing them to invoke `setState()` and modify the context's internal variables directly.

## Implementation Examples from CS-Notes

### Strategy Pattern: Duck Behavior

The CS-Notes repository demonstrates Strategy using a duck simulation where quacking behavior can be swapped at runtime. In `notes/设计模式 - 策略.md`, the `Duck` class acts as the context holding a `QuackBehavior` reference, with concrete strategies `Quack` and `Squeak` implementing the algorithm interface.

```java
// Strategy interface defined in notes/设计模式 - 策略.md
public interface QuackBehavior {
    void quack();
}

// Concrete strategies
public class Quack implements QuackBehavior {
    @Override 
    public void quack() { 
        System.out.println("quack!"); 
    }
}

public class Squeak implements QuackBehavior {
    @Override 
    public void quack() { 
        System.out.println("squeak!"); 
    }
}

// Context class
public class Duck {
    private QuackBehavior quackBehavior;
    
    public void performQuack() { 
        if (quackBehavior != null) 
            quackBehavior.quack(); 
    }
    
    public void setQuackBehavior(QuackBehavior qb) { 
        this.quackBehavior = qb; 
    }
}

// Client explicitly selects strategy
public class Client {
    public static void main(String[] args) {
        Duck duck = new Duck();
        duck.setQuackBehavior(new Squeak());
        duck.performQuack();   // Output: squeak!
        duck.setQuackBehavior(new Quack());
        duck.performQuack();   // Output: quack!
    }
}

```

### State Pattern: Gumball Machine

The State pattern implementation in `notes/设计模式 - 状态.md` models a gumball machine that behaves differently based on whether it has a quarter, is sold out, or is dispensing. The `GumballMachine` context delegates all actions (`insertQuarter()`, `turnCrank()`, `dispense()`) to its current `State` object, while concrete states like `NoQuarterState` manage the transitions.

```java
// State interface from notes/设计模式 - 状态.md
public interface State {
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
}

// Concrete state with back-reference to context
public class NoQuarterState implements State {
    private GumballMachine machine;
    
    public NoQuarterState(GumballMachine m) { 
        this.machine = m; 
    }
    
    @Override 
    public void insertQuarter() {
        System.out.println("You insert a quarter");
        machine.setState(machine.getHasQuarterState());
    }
    
    // Other methods handle invalid actions for this state
}

// Context class managing state instances
public class GumballMachine {
    private State noQuarterState, hasQuarterState, soldState, soldOutState;
    private State state;
    private int count;
    
    public GumballMachine(int n) {
        count = n;
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        soldOutState = new SoldOutState(this);
        state = (n > 0) ? noQuarterState : soldOutState;
    }
    
    // Delegates to current state
    public void insertQuarter() { state.insertQuarter(); }
    public void turnCrank() { state.turnCrank(); state.dispense(); }
    public void setState(State s) { this.state = s; }
    public State getHasQuarterState() { return hasQuarterState; }
}

// Client interaction triggers internal state changes
public class Client {
    public static void main(String[] args) {
        GumballMachine gm = new GumballMachine(5);
        gm.insertQuarter(); // Transitions to HasQuarterState internally
        gm.turnCrank();     // Transitions to SoldState, then NoQuarterState
    }
}

```

## When to Use Each Pattern

Choose **Strategy** when you need multiple interchangeable algorithms (sorting, formatting, validation) that can be selected at runtime by client code. Use **State** when an object must exhibit different behavior depending on its lifecycle phase or conditions, and those phases have complex transition logic that should be encapsulated separately from the context.

## Summary

- **Strategy** encapsulates algorithms; **State** encapsulates lifecycle phases and transitions.
- **Strategy** transitions are triggered externally by the client calling `setStrategy()`; **State** transitions are triggered internally by concrete state classes calling `setState()` on the context.
- **Strategy** maintains loose coupling with no back-references; **State** requires concrete states to hold references to the context to facilitate transitions.
- Both patterns rely on delegation, but Strategy represents static algorithm selection while State represents dynamic behavioral composition.

## Frequently Asked Questions

### Can the Strategy and State patterns be used together in the same application?

Yes, these patterns are complementary. You might use **State** to manage high-level object phases (like connection states in a network client) while using **Strategy** within specific states to vary algorithmic behavior (like different compression strategies during an active connection). The CS-Notes repository documents both patterns independently in `notes/设计模式 - 目录.md` for this reason.

### How does client code interaction differ between Strategy and State implementations?

With **Strategy**, the client explicitly instantiates and assigns strategies using methods like `setQuackBehavior()`, maintaining full control over which algorithm executes. With **State**, the client simply invokes actions like `insertQuarter()` or `turnCrank()` on the context, remaining unaware of the current state or the transition logic that determines the next behavioral phase.

### Which pattern is better for implementing a finite state machine?

The **State** pattern is the canonical choice for finite state machines because it models states as discrete objects with explicit transition logic. Each state class (e.g., `HasQuarterState`) encapsulates both the behavior for that state and the rules for moving to subsequent states, preventing the complex conditional logic that would clutter a monolithic context class.

### Why do State pattern implementations typically show higher coupling than Strategy pattern implementations?

Concrete state classes in the **State** pattern require back-references to the context (e.g., `private GumballMachine machine`) so they can trigger transitions by calling `machine.setState()`. This necessity creates bidirectional dependencies between states and context. In contrast, **Strategy** concrete classes are purely algorithmic and receive all necessary data through method parameters, maintaining unidirectional dependency from context to strategy only.