Skip to main content

🧩 State Pattern

βœ… Intent​

  • Represent an object's state as dedicated classes, with behavior defined per state
  • The current state directly determines which behavior to execute

βœ… Motivation​

  • Separates behavior per state into classes, ensuring clear responsibility separation
  • Since each state object knows the transition rules, state control is explicit and manageable

βœ… When to Use​

  • For UI or business flows involving steps, transitions, or mode switching
  • When many states are expected and future expansion is likely

βœ… Code Example​

// ηŠΆζ…‹γ‚€γƒ³γ‚ΏγƒΌγƒ•γ‚§γƒΌγ‚Ή
interface DocumentState {
publish(context: DocumentContext): void;
}

// ηŠΆζ…‹γ‚―γƒ©γ‚ΉοΌˆdraftοΌ‰
class DraftState implements DocumentState {
publish(context: DocumentContext): void {
console.log("レビγƒ₯ー依頼を送俑");
context.setState(new ReviewState());
}
}

// ηŠΆζ…‹γ‚―γƒ©γ‚ΉοΌˆreviewοΌ‰
class ReviewState implements DocumentState {
publish(context: DocumentContext): void {
console.log("ε…¬ι–‹γ—γΎγ—γŸ");
context.setState(new PublishedState());
}
}

// ηŠΆζ…‹γ‚―γƒ©γ‚ΉοΌˆpublishedοΌ‰
class PublishedState implements DocumentState {
publish(context: DocumentContext): void {
console.log("γ™γ§γ«ε…¬ι–‹ζΈˆγΏγ§γ™");
}
}

// γ‚³γƒ³γƒ†γ‚­γ‚Ήγƒˆ
class DocumentContext {
private state: DocumentState;

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

setState(state: DocumentState): void {
this.state = state;
}

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

// εˆ©η”¨δΎ‹
const doc = new DocumentContext();
doc.publish(); // β†’ レビγƒ₯ー依頼
doc.publish(); // β†’ ε…¬ι–‹
doc.publish(); // β†’ γ™γ§γ«ε…¬ι–‹ζΈˆγΏ

βœ… Explanation​

This code applies the State pattern to switch behavior based on the document's state (Draft, Review, Published).
The State pattern allows an object to change its behavior based on its internal state, eliminating conditional branches and improving readability and maintainability.

1. Overview of the State Pattern​

  • State: Interface defining behavior for each state

    • Represented by DocumentState in this code
  • ConcreteState: Implements the State interface and provides state-specific behavior

    • Represented by DraftState, ReviewState, and PublishedState
  • Context: Maintains the current state and delegates behavior to it

    • Represented by DocumentContext

2. Key Classes and Their Roles​

  • DocumentState

    • Common interface for all states
    • Declares the method publish(context: DocumentContext): void
  • DraftState

    • Concrete state for the "draft" phase
    • The publish method sends a review request and transitions to ReviewState
  • ReviewState

    • Concrete state for the "under review" phase
    • The publish method publishes the document and transitions to PublishedState
  • PublishedState

    • Concrete state for the "published" phase
    • The publish method outputs a message indicating that the document is already published
  • DocumentContext

    • The context class that maintains the current state
    • Calls the state's publish method and manages transitions using setState

3. UML Class Diagram​

4. Benefits of the State Pattern​

  • Eliminates Conditional Branching: Each state's logic is encapsulated in a separate class
  • Extensibility: New states can be added by implementing DocumentState
  • Runtime Flexibility: The state can be changed dynamically during execution

This design clearly separates behavior by state and allows safe, manageable state transitions.
It is especially effective when multiple states exist and each has distinct behavior.