State Pattern
State Pattern: Behavior That Changes with State
Section titled “State Pattern: Behavior That Changes with State”Now let’s dive into the State Pattern - one of the most elegant behavioral design patterns that allows an object to alter its behavior when its internal state changes. The object will appear to change its class!
Why State Pattern?
Section titled “Why State Pattern?”Imagine a vending machine. When it has no money inserted, pressing the dispense button does nothing. When money is inserted, pressing dispense gives you a product. When it’s out of stock, it refunds your money. The machine behaves differently based on its state. The State Pattern works the same way!
The State Pattern allows an object to change its behavior when its internal state changes. Instead of having giant if/else or switch statements checking the state, each state becomes its own class that knows how to handle requests for that state.
What’s the Use of State Pattern?
Section titled “What’s the Use of State Pattern?”The State Pattern is useful when:
- Object behavior depends on state - Different actions based on internal state
- You have complex state-dependent logic - Many if/else checking state
- State transitions are well-defined - Clear rules for state changes
- You want to add new states easily - Without modifying existing code
- States should be explicit - Each state is a first-class object
What Happens If We Don’t Use State Pattern?
Section titled “What Happens If We Don’t Use State Pattern?”Without the State Pattern, you might:
- Giant switch/if-else statements - Checking state everywhere
- Scattered state logic - Same checks in multiple methods
- Hard to add states - Modify many places for new state
- Violation of OCP - Need to modify existing code
- Difficult to understand - State behavior spread across methods
Simple Example: The Document Workflow
Section titled “Simple Example: The Document Workflow”Let’s start with a super simple example that anyone can understand!
Visual Representation
Section titled “Visual Representation”State Transitions
Section titled “State Transitions”Here’s how the document transitions between states:
stateDiagram-v2
[*] --> Draft: Create Document
Draft --> Draft: edit()
Draft --> Moderation: publish()
Moderation --> Published: approve()
Moderation --> Draft: reject()
Published --> Draft: edit()
Published --> [*]: archive()
note right of Draft: Can edit freely
note right of Moderation: Under review
note right of Published: Live content
Interaction Flow
Section titled “Interaction Flow”sequenceDiagram
participant Client
participant Document
participant DraftState
participant ModerationState
participant PublishedState
Client->>Document: new Document()
Document->>DraftState: set initial state
Client->>Document: edit("New content")
activate Document
Document->>DraftState: edit(document)
DraftState->>DraftState: Update content
DraftState-->>Document: Content updated
deactivate Document
Client->>Document: publish()
activate Document
Document->>DraftState: publish(document)
DraftState->>Document: set_state(ModerationState)
DraftState-->>Document: Sent to moderation
deactivate Document
Note over Client,PublishedState: State changed! Same method, different behavior
Client->>Document: publish()
activate Document
Document->>ModerationState: publish(document)
ModerationState->>Document: set_state(PublishedState)
ModerationState-->>Document: Published!
deactivate Document
The Problem
Section titled “The Problem”You’re building a document management system where documents go through different states (Draft, Moderation, Published). Without State Pattern:
Problems:
- State checks scattered across every method
- Adding a new state requires modifying ALL methods
- Hard to understand what each state does
- Violates Open/Closed Principle
The Solution: State Pattern
Section titled “The Solution: State Pattern”Class Structure
Section titled “Class Structure”classDiagram
class DocumentState {
<<interface>>
+edit(doc, content) void
+publish(doc) void
+reject(doc) void
}
class DraftState {
+edit(doc, content) void
+publish(doc) void
+reject(doc) void
}
class ModerationState {
+edit(doc, content) void
+publish(doc) void
+reject(doc) void
}
class PublishedState {
+edit(doc, content) void
+publish(doc) void
+reject(doc) void
}
class Document {
-state: DocumentState
-content: str
+set_state(state) void
+edit(content) void
+publish() void
+reject() void
}
DocumentState <|.. DraftState : implements
DocumentState <|.. ModerationState : implements
DocumentState <|.. PublishedState : implements
Document --> DocumentState : delegates to
note for DocumentState "Each state knows how\nto handle requests"
note for Document "Context delegates\nto current state"
Real-World Software Example: Order Processing System
Section titled “Real-World Software Example: Order Processing System”Now let’s see a realistic software example - an e-commerce order processing system with multiple states.
The Problem
Section titled “The Problem”You’re building an order system where orders go through states: Pending → Paid → Shipped → Delivered (or Cancelled at various points). Without State Pattern:
Problems:
- 5 states × 4 methods = 20 if-else branches!
- Adding a new state requires modifying ALL methods
- State behavior scattered across methods
- Very error-prone and hard to maintain
The Solution: State Pattern
Section titled “The Solution: State Pattern”State Diagram
Section titled “State Diagram”stateDiagram-v2
[*] --> Pending: Create Order
Pending --> Paid: pay()
Pending --> Cancelled: cancel()
Paid --> Shipped: ship()
Paid --> Cancelled: cancel() + refund
Shipped --> Delivered: deliver()
Delivered --> [*]: Complete
Cancelled --> [*]: Complete
note right of Pending: Awaiting payment
note right of Paid: Ready to ship
note right of Shipped: In transit
note right of Delivered: Complete!
note right of Cancelled: Order cancelled
State Pattern Variants
Section titled “State Pattern Variants”There are different ways to implement the State Pattern:
1. States as Singletons
Section titled “1. States as Singletons”When states are stateless, they can be singletons:
Pros: Memory efficient, no unnecessary object creation
Cons: States can’t hold instance-specific data
2. State with History
Section titled “2. State with History”Track state history for auditing:
3. Hierarchical States
Section titled “3. Hierarchical States”States can have sub-states:
When to Use State Pattern?
Section titled “When to Use State Pattern?”Use State Pattern when:
✅ Object behavior depends on state - Different actions for different states
✅ You have many state-checking conditionals - if/else chains everywhere
✅ State transitions are well-defined - Clear rules for state changes
✅ You want to add states easily - Without modifying existing code
✅ States should be explicit - First-class state objects
When NOT to Use State Pattern?
Section titled “When NOT to Use State Pattern?”Don’t use State Pattern when:
❌ Few states with simple transitions - Direct if/else might be clearer
❌ State doesn’t affect behavior - Just data, not behavior
❌ States are not well-defined - Unclear transitions
❌ Over-engineering - Don’t add complexity for 2-3 simple states
Common Mistakes to Avoid
Section titled “Common Mistakes to Avoid”Mistake 1: State Objects Holding Context Reference Permanently
Section titled “Mistake 1: State Objects Holding Context Reference Permanently”Mistake 2: Context Knowing About All Concrete States
Section titled “Mistake 2: Context Knowing About All Concrete States”Mistake 3: Missing Default Behavior in States
Section titled “Mistake 3: Missing Default Behavior in States”Benefits of State Pattern
Section titled “Benefits of State Pattern”- No if/else chains - Each state handles its own behavior
- Easy to add states - Just create a new state class
- Single Responsibility - Each state has one job
- Open/Closed Principle - Add states without modifying existing code
- Explicit state machine - State diagram maps to code
- Testable - Each state can be tested independently
Revision: Quick Catch-Up
Section titled “Revision: Quick Catch-Up”What is State Pattern?
Section titled “What is State Pattern?”State Pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. The object appears to change its class.
Why Use It?
Section titled “Why Use It?”- ✅ Eliminate if/else chains - State checks spread everywhere
- ✅ Easy to add states - New state = new class
- ✅ Clear state behavior - All behavior in one place
- ✅ Explicit transitions - States control transitions
- ✅ Follow Open/Closed Principle
How It Works?
Section titled “How It Works?”- Define State interface - Methods for all state behaviors
- Create Concrete States - Each state implements interface
- Create Context - Holds current state, delegates to it
- States change Context state - Transitions happen in states
- Client uses Context - Doesn’t know about states
Key Components
Section titled “Key Components”Context → State Interface → Concrete States- State - Interface for state behavior
- Concrete State - Specific state implementation
- Context - Object whose behavior changes
- Client - Uses context, unaware of states
Simple Example
Section titled “Simple Example”class State(ABC): @abstractmethod def handle(self, context): pass
class ConcreteStateA(State): def handle(self, context): print("State A behavior") context.set_state(ConcreteStateB())
class Context: def __init__(self): self._state = ConcreteStateA()
def set_state(self, state): self._state = state
def request(self): self._state.handle(self)When to Use?
Section titled “When to Use?”✅ Object behavior depends on state
✅ Many if/else checking state
✅ Well-defined state transitions
✅ Need to add states easily
✅ States should be explicit
When NOT to Use?
Section titled “When NOT to Use?”❌ Few simple states
❌ State doesn’t affect behavior
❌ Unclear transitions
❌ Over-engineering
Key Takeaways
Section titled “Key Takeaways”- State Pattern = Behavior changes with state
- State = Encapsulates state-specific behavior
- Context = Delegates to current state
- Benefit = No if/else, easy to extend
- Principle = Open for extension, closed for modification
Interview Focus: State Pattern
Section titled “Interview Focus: State Pattern”Key Points to Remember
Section titled “Key Points to Remember”1. Core Concept
Section titled “1. Core Concept”What to say:
“State Pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. Instead of having if/else chains checking state, each state becomes its own class that handles behavior for that state. The object appears to change its class.”
Why it matters:
- Shows you understand the fundamental purpose
- Demonstrates knowledge of eliminating conditionals
- Indicates you can explain concepts clearly
Must discuss:
- State - Object changes behavior based on INTERNAL state, automatic
- Strategy - Client chooses behavior EXTERNALLY, explicit
- Key difference - Who controls the change and why
Example to give:
“State Pattern is like a traffic light that automatically changes behavior based on its internal state - red means stop, green means go. Strategy Pattern is like choosing a route on GPS - YOU explicitly choose the algorithm. With State, transitions happen automatically based on internal logic. With Strategy, you explicitly set which algorithm to use.”
3. Benefits and Trade-offs
Section titled “3. Benefits and Trade-offs”Benefits to mention:
- No if/else chains - Clean, maintainable code
- Easy to add states - Just create new class
- Single Responsibility - Each state handles its behavior
- Open/Closed Principle - Add without modifying
- Explicit state machine - Code mirrors state diagram
Trade-offs to acknowledge:
- More classes - Each state is a class
- Overkill for simple states - 2-3 states might not need it
- Can be complex - Many states with many methods
4. Common Interview Questions
Section titled “4. Common Interview Questions”Q: “How does State Pattern differ from Strategy Pattern?”
A:
“Both encapsulate behavior in separate classes, but State changes behavior based on internal state automatically, while Strategy lets the client explicitly choose the algorithm. State objects typically know about other states and handle transitions. Strategy objects are usually stateless and interchangeable. State is about ‘what state am I in?’, Strategy is about ‘which algorithm should I use?’”
Q: “Where would you use State Pattern in a real system?”
A:
“I’d use State Pattern for order processing systems (pending, paid, shipped, delivered), document workflows (draft, review, published), connection handling (connecting, connected, disconnected), or UI components (enabled, disabled, loading). Any system where objects go through well-defined states with different behavior.”
Q: “How do you handle state transitions?”
A:
“State transitions can be handled in two ways: 1) States handle their own transitions - each state knows what the next state should be and calls context.setState(). 2) Context handles transitions - context decides next state based on rules. The first approach is cleaner because each state encapsulates its transition logic.”
Interview Checklist
Section titled “Interview Checklist”Before your interview, make sure you can:
- Define State Pattern clearly in one sentence
- Explain when to use it (with examples)
- Compare State vs Strategy Pattern
- Implement State Pattern from scratch
- List benefits and trade-offs
- Connect to SOLID principles
- Identify when NOT to use it
- Give 2-3 real-world examples
- Discuss state transition approaches
- Draw a state diagram for an example
Remember: State Pattern is about letting objects change behavior when their state changes - no more giant if/else state machines! 🔄