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.