3 min read

State Pattern

The State Pattern is a behavioral design pattern that lets an object alter its behavior when its internal state changes. It appears as if the object changed its class.

1. The Core Concept

The pattern is closely related to the concept of a Finite State Machine.

  • Context: The main object (e.g., a Document). It holds a reference to the current state object.
  • State Interface: Defines methods for all state-specific behaviors.
  • Concrete States: Implement behaviors specific to a state (e.g., Draft, Moderation, Published).

Instead of a massive switch statement inside the Context (switch (state) { case 'DRAFT': ... }), the Context delegates the work to the current State object.

2. Analogy: Smartphone Buttons

Consider the power button on your phone:

  • If Screen is Off: Pressing it turns the screen On.
  • If Screen is On: Pressing it turns the screen Off.
  • If Phone is Locked: Pressing it might show the lock screen.

The button is the same, but the behavior changes based on the phone's state.

3. Example (TypeScript)

Let's model a simple Document workflow.

// The State Interface
interface State {
    publish(): void;
}

// The Context
class Document {
    private state: State;

    constructor() {
        this.state = new DraftState(this);
    }

    changeState(state: State) {
        this.state = state;
    }

    publish() {
        this.state.publish();
    }
}

// Concrete State 1: Draft
class DraftState implements State {
    private document: Document;

    constructor(document: Document) {
        this.document = document;
    }

    publish() {
        console.log("Draft published. Moving to Moderation.");
        this.document.changeState(new ModerationState(this.document));
    }
}

// Concrete State 2: Moderation
class ModerationState implements State {
    private document: Document;

    constructor(document: Document) {
        this.document = document;
    }

    publish() {
        console.log("Moderation passed. Document is now Live.");
        this.document.changeState(new PublishedState(this.document));
    }
}

// Concrete State 3: Published
class PublishedState implements State {
    private document: Document;

    constructor(document: Document) {
        this.document = document;
    }

    publish() {
        console.log("Document is already published.");
    }
}

// Usage
const doc = new Document();
doc.publish(); // Output: Draft published. Moving to Moderation.
doc.publish(); // Output: Moderation passed. Document is now Live.
doc.publish(); // Output: Document is already published.

4. State vs. Strategy

They look very similar (both use composition to delegate behavior), but the intent differs.

  • Strategy: The Client usually chooses the strategy (e.g., "Use PayPal"). Strategies are often independent and unaware of each other.
  • State: The State objects often know about each other and initiate transitions (e.g., Draft moves itself to Moderation). The state transitions are part of the logic.

5. Pros and Cons

Pros Cons
SRP: Organizes code related to specific states into separate classes. Complexity: Overkill if the state machine has only a few states or rarely changes.
Open/Closed: Add new states without changing existing state classes or the context. Coupling: State classes often depend on the Context (to trigger transitions).
Simplification: Removes massive conditional logic (if/else or switch) from the context.

6. Finite State Machines (FSM)

A Finite State Machine (FSM) is a mathematical model of computation. It is an abstract machine that can be in exactly one of a finite number of states at any given time.

Components

  • States: A finite set of conditions (e.g., Idle, Running, Paused).
  • Transitions: Rules that dictate how the machine moves from one state to another (e.g., Idle -> Running).
  • Events (Inputs): Triggers that cause transitions (e.g., Press Start Button).

Relation to State Pattern

The State Pattern is essentially an object-oriented implementation of a Finite State Machine.

  • Each State in the FSM becomes a concrete class.
  • Transitions are logic inside these classes that switch the Context to a new State class.

programming/design-patterns programming/object-oriented-programming programming/strategy-pattern