Post

Software Design - State Pattern

Explore the State Pattern, its structure, use cases, and benefits in software design.

Software Design - State Pattern

Definition

Imagine a TV remote:

  • Off (❌): Press power ➔ TV turns on.
  • On (✅): Press power ➔ TV turns off.
  • Mute (🔇): TV is silent; pressing mute brings back the sound.

The State Pattern is a behavioral design pattern that allows an object to change its behavior based on its internal state.
Instead of using many if-else conditions, behavior is delegated to state-specific classes.

Structure

State Pattern Structure State Pattern Structure taken from Refactoring Guru

  • Encapsulate state-specific behavior into separate classes.
  • State objects handle transitions between states.
  • Allows dynamic behavior changes at runtime.
  • Follows the Open/Closed Principle: Easily add new states without modifying existing code.

Key Characteristics

  • Encapsulates State-Specific Behavior ➔ Organized code with each behavior in its own class.
  • State Objects Handle Transitions ➔ Context object doesn’t manage transitions; states do.
  • Allows Dynamic Behavior Changes ➔ Switching states changes behavior dynamically.
  • Open/Closed Principle Compliance ➔ Add new states easily without changing existing code.

When to Use

Complex State-Dependent Behavior

  • Ex: Document editor in Draft, Review, Published states.

Eliminating Large Conditionals

  • Ex: Vending machine with states like Idle, HasMoney, Dispensing.

State-Specific Operations

  • Ex: Media player handling Playing, Paused, Stopped.

Runtime State Changes

  • Ex: Phone switching between Normal Mode, Battery Saver Mode.

When NOT to Use

Simple State Transitions
Resource Constraints (due to extra classes/objects)
Unpredictable State Changes
Centralized State Transition Logic
Short-Lived Objects (no meaningful state change during lifespan)

Code Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# State Interface
class OrderState:
    def proceed(self, order):
        raise NotImplementedError("Subclasses must implement this!")

# Concrete States
class ReceivedState(OrderState):
    def proceed(self, order):
        print("Order received. Now processing the order.")
        order.state = ProcessingState()
class ProcessingState(OrderState):
    def proceed(self, order):
        print("Order is being processed. Now dispatching the order.")
        order.state = DispatchedState()
class DispatchedState(OrderState):
    def proceed(self, order):
        print("Order has been dispatched. Delivery in progress.")
        # Final state; no transition here.

# Context
class Order:
    def __init__(self, state: OrderState):
        self.state = state
    def next(self):
        self.state.proceed(self)

# Demonstration:
if __name__ == '__main__':
    order = Order(ReceivedState())
    order.next()  # Transitions from Received to Processing.
    order.next()  # Transitions from Processing to Dispatched.
    order.next()  # No further transition

Real World Examples

  • Vending Machine
    • System: Vending Machine
    • Interface: VendingMachineState
    • Concrete States: IdleState, HasMoneyState, DispensingState, OutOfStockState
    • Context: VendingMachine
  • Video Game Character
    • System: Video Game Character
    • Interface: CharacterState
    • Concrete States: IdleState, RunningState, AttackingState, DeadState
    • Context: GameCharacter
  • Chat App User Presence
    • System: Chat App User Presence
    • Interface: PresenceState
    • Concrete States: OnlineState, OfflineState, AwayState, BusyState
    • Context: UserPresence
  • ATM Machine
    • System: ATM Machine
    • Interface: ATMState
    • Concrete States: NoCardState, HasCardState, AuthorizedState, NoCashState
    • Context: ATMMachine
  • Elevator System
    • System: Elevator System
    • Interface: ElevatorState
    • Concrete States: IdleState, MovingUpState, MovingDownState, DoorOpenState
    • Context: ElevatorController
  • Document Workflow System
    • System: Document Workflow System
    • Interface: DocumentState
    • Concrete States: DraftState, ReviewState, PublishedState, ArchivedState
    • Context: Document
  • E-commerce Product Lifecycle
    • System: E-commerce Product Lifecycle
    • Interface: ProductState
    • Concrete States: NewProductState, ActiveState, DiscontinuedState
    • Context: Product
  • Printer Job Management
    • System: Printer Job Management
    • Interface: PrintJobState
    • Concrete States: QueuedState, PrintingState, CompletedState, ErrorState
    • Context: PrintJob
This post is licensed under CC BY 4.0 by the author.