State Pattern

The State is a behavioral design pattern that allows an object to change its behavior when its internal state changes, making it appear as if the object changed its class. It encapsulates state-specific behavior in separate classes, promoting clean, maintainable code for objects with multiple states and transitions.

Key Principles

  • Encapsulate State: Each state is a class implementing common interface.
  • Delegate Behavior: Context forwards requests to current state object.
  • Explicit Transitions: States handle transitions (e.g., next()).
  • Open/Closed: Add new states without modifying context.

Structure

  • State Interface: Common methods for all states.
  • Concrete State: Implements state-specific behavior and transitions.
  • Context: Holds reference to current state; delegates calls.

Python Example: Traffic Light

from abc import ABC, abstractmethod

# State Interface
class TrafficLightState(ABC):
    @abstractmethod
    def next(self, light):
        pass

    @abstractmethod
    def display(self):
        pass

# Concrete States
class Red(TrafficLightState):
    def next(self, light):
        light.set_state(Green())

    def display(self):
        return "RED – Stop"

class Green(TrafficLightState):
    def next(self, light):
        light.set_state(Yellow())

    def display(self):
        return "GREEN – Go"

class Yellow(TrafficLightState):
    def next(self, light):
        light.set_state(Red())

    def display(self):
        return "YELLOW – Caution"

# Context
class TrafficLight:
    def __init__(self):
        self._state = Red()  # Initial state

    def set_state(self, state: TrafficLightState):
        self._state = state
        print(f"State changed to {state.__class__.__name__}")

    def next(self):
        self._state.next(self)

    def display(self):
        return self._state.display()

# Usage (Client Code)
if __name__ == "__main__":
    light = TrafficLight()

    print(light.display())  # RED – Stop
    light.next()
    print(light.display())  # GREEN – Go
    light.next()
    print(light.display())  # YELLOW – Caution
    light.next()
    print(light.display())  # RED – Stop

Output:

RED – Stop
State changed to Green
GREEN – Go
State changed to Yellow
YELLOW – Caution
State changed to Red
RED – Stop

When to Use State

  • Many States: Object behavior varies significantly by state (e.g., TCP connection: LISTEN → ESTABLISHED → CLOSED).
  • Conditional Logic: Avoid large if/else or switch statements.
  • State Transitions: Clear, explicit rules.
  • Avoid: Few states (use simple attributes).

Summary: State delegates behavior to interchangeable state objects, allowing an object to alter its actions dynamically based on internal state without conditional sprawl.