Skip to main content

🧩 State Pattern

βœ… Intent​

  • Change an object's behavior based on its current state
  • Delegate state-specific responsibilities to separate classes

βœ… Motivation​

  • Effective when user types can be treated as internal states
  • Even the logic for changing state itself can be handled by the state objects

βœ… When to Use​

  • When the current state becomes the central concern, such as user rank or login status
  • When you need controlled state transitions

βœ… Code Example​

// ηŠΆζ…‹γ‚€γƒ³γ‚ΏγƒΌγƒ•γ‚§γƒΌγ‚Ή
interface DiscountState {
calculate(basePrice: number): number;
}

// ε„ηŠΆζ…‹γ‚―γƒ©γ‚Ή
class StudentState implements DiscountState {
calculate(basePrice: number): number {
return basePrice * 0.8;
}
}

class MemberState implements DiscountState {
calculate(basePrice: number): number {
return basePrice * 0.9;
}
}

class VIPState implements DiscountState {
calculate(basePrice: number): number {
return basePrice * 0.7;
}
}

class DefaultState implements DiscountState {
calculate(basePrice: number): number {
return basePrice;
}
}

// γ‚³γƒ³γƒ†γ‚­γ‚Ήγƒˆ
class DiscountContext {
private state: DiscountState;

constructor(state: DiscountState) {
this.state = state;
}

setState(state: DiscountState) {
this.state = state;
}

calculate(basePrice: number): number {
return this.state.calculate(basePrice);
}
}

// εˆ©η”¨δΎ‹
const context = new DiscountContext(new StudentState());
console.log(context.calculate(1000)); // 800

βœ… Explanation​

This code applies the State pattern to isolate discount logic into separate states that can be switched dynamically.
The State pattern allows an object to alter its behavior based on internal state, eliminating conditional branches and improving readability and maintainability.

1. Overview of the State Pattern​

  • State: Defines an interface for behavior specific to each state

    • Represented here by DiscountState
  • ConcreteState: Implements the State interface to provide specific behavior for each state

    • Implemented by StudentState, MemberState, VIPState, and DefaultState in this code
  • Context: Holds the current state and delegates behavior based on it

    • Represented by DiscountContext in this code

2. Key Classes and Their Roles​

  • DiscountState

    • Common interface for discount calculation
    • Defines the method calculate(basePrice: number): number
  • StudentState, MemberState, VIPState, DefaultState

    • Concrete state classes implementing DiscountState
    • Each applies a different discount rate
  • DiscountContext

    • Context class that maintains the current state
    • Allows switching state via setState, and executes the discount calculation via the current state's calculate method

3. UML Class Diagram​

4. Benefits of the State Pattern​

  • Eliminates Conditional Branching: By moving logic into state classes, conditionals can be eliminated
  • Extensibility: Adding a new state requires only implementing DiscountState
  • Dynamic Switching: Allows state transitions at runtime in a clean and controlled way

This design clearly separates behavior by state and provides a safe mechanism for managing transitionsβ€”especially effective in scenarios with growing conditional logic.