Behavioral PatternsState PatternHard⏱️ ~3 min

State Pattern Trade-offs and When to Use

When to Use State Pattern

State Pattern is appropriate when your object exhibits these characteristics:

First, the object's behavior changes significantly based on its state. Simple property changes do not justify this pattern. Second, you have multiple states (typically 3 or more) with different behavior for the same operations. Third, you find yourself writing large conditional blocks (if-else, switch-case) based on state fields scattered across multiple methods.

Fourth, state transitions follow business logic rules that states themselves understand best. Fifth, you expect to add new states in the future without modifying existing code.

When State Pattern Is Overkill

Avoid State Pattern when:

  • Only 2 states exist: A simple boolean flag with if-else is clearer than separate state classes.
  • States have identical behavior: If all states handle operations the same way, you just need a status field, not the pattern.
  • No behavior variation: If state only affects data (not behavior), use a simple enum or status field.
  • Transitions are purely data-driven: If a state machine diagram with just data conditions suffices, use a FSM (Finite State Machine) library instead.

State Pattern vs Strategy Pattern

State Pattern
Purpose: Manage behavior changes as object's state changes

Who decides: States trigger transitions themselves

Client aware: No, client just calls context methods

Relationship: States know about each other for transitions
Strategy Pattern
Purpose: Make algorithm interchangeable

Who decides: Client or context chooses strategy explicitly

Client aware: Yes, client picks which strategy to use

Relationship: Strategies are independent, unaware of each other

State Pattern vs Simple Enum

Use Enum when: You only need to track status for queries or display. Example: Order status (PENDING, SHIPPED, DELIVERED) where each status just stores data but does not change how cancel() or refund() behave.

Use State Pattern when: Different states execute operations differently. Example: A vending machine's insertMoney() behaves completely differently in IdleState versus DispensingState. The behavior change is substantial, not just a label change.

Advantages

  • Single Responsibility Principle (SRP): Each state class handles one state's behavior
  • Open/Closed Principle (OCP): Add new states without modifying existing state classes
  • Eliminates conditional complexity: No nested if-else blocks based on state
  • Explicit state transitions: Transitions are clear method calls, not buried in conditions

Disadvantages

  • Increased class count: Each state requires a separate class, increasing codebase size
  • Indirection: Following execution flow requires jumping between context and state classes
  • Overkill for simple cases: A two-state system with minimal behavior difference is clearer with if-else
  • Shared state complexity: If states need to share complex data, you must carefully design context's API
Interview Tip: Be prepared to justify your choice. If asked "Why not just use if-else?", explain the specific Open/Closed violation: "Every time we add a new state, we would need to modify every method that checks state. With State Pattern, we just add a new state class."
💡 Key Takeaways
Use when behavior changes significantly across 3+ states
Avoid for binary states or when only data changes, not behavior
State Pattern states trigger transitions; Strategy Pattern client chooses strategy
States know about each other; strategies are independent
Trades class count for eliminating conditional complexity
📌 Examples
1Good: Document workflow with approval logic varying by state
2Good: Game character with different movement in walking/swimming/flying states
3Bad: User account with just active/inactive flag
4Bad: Payment status that only affects display labels
← Back to State Pattern Overview