0
0
LldComparisonIntermediate · 4 min read

Strategy vs State Pattern: Key Differences and When to Use Each

The Strategy pattern lets you swap algorithms or behaviors dynamically by encapsulating them in separate classes, while the State pattern manages an object's internal state and changes its behavior when the state changes. Both use composition and polymorphism but differ in intent: Strategy focuses on interchangeable algorithms, and State focuses on state-driven behavior changes.
⚖️

Quick Comparison

This table summarizes the main differences between the Strategy and State patterns.

AspectStrategy PatternState Pattern
PurposeEncapsulate interchangeable algorithms or behaviorsManage object behavior based on internal state changes
FocusAlgorithm selectionState-driven behavior
Context RoleUses a strategy object to perform behaviorHolds a state object representing current state
Behavior ChangeBehavior changes by swapping strategyBehavior changes automatically when state changes
State AwarenessContext is unaware of strategy internalsContext and states are tightly coupled
Use Case ExampleSorting algorithms, payment methodsTCP connection states, vending machine states
⚖️

Key Differences

The Strategy pattern is designed to let a client choose from multiple algorithms or behaviors at runtime. It defines a family of algorithms, encapsulates each one, and makes them interchangeable. The context class holds a reference to a strategy object and delegates the behavior to it. The context is unaware of the details of the strategy, promoting loose coupling.

In contrast, the State pattern models an object's behavior as a set of states. Each state is a class that implements behavior specific to that state. The context maintains a reference to the current state and delegates requests to it. When the state changes, the context's behavior changes automatically without the client needing to know about the state transitions.

While both patterns use composition and polymorphism, the Strategy pattern focuses on selecting an algorithm independently of the object's state, whereas the State pattern tightly couples behavior to the object's internal state and manages transitions between states internally.

⚖️

Code Comparison

Here is an example showing the Strategy pattern where a context uses different payment methods as strategies.

python
from abc import ABC, abstractmethod

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: float) -> None:
        pass

class CreditCardPayment(PaymentStrategy):
    def pay(self, amount: float) -> None:
        print(f"Paying {amount} using Credit Card.")

class PayPalPayment(PaymentStrategy):
    def pay(self, amount: float) -> None:
        print(f"Paying {amount} using PayPal.")

class ShoppingCart:
    def __init__(self, payment_strategy: PaymentStrategy):
        self.payment_strategy = payment_strategy

    def checkout(self, amount: float) -> None:
        self.payment_strategy.pay(amount)

# Usage
cart = ShoppingCart(CreditCardPayment())
cart.checkout(100.0)
cart.payment_strategy = PayPalPayment()
cart.checkout(200.0)
Output
Paying 100.0 using Credit Card. Paying 200.0 using PayPal.
↔️

State Pattern Equivalent

This example shows the State pattern where a TCP connection changes behavior based on its state.

python
from abc import ABC, abstractmethod

class TCPState(ABC):
    @abstractmethod
    def open(self, connection):
        pass

    @abstractmethod
    def close(self, connection):
        pass

class ClosedState(TCPState):
    def open(self, connection):
        print("Opening connection.")
        connection.state = OpenState()

    def close(self, connection):
        print("Connection already closed.")

class OpenState(TCPState):
    def open(self, connection):
        print("Connection already open.")

    def close(self, connection):
        print("Closing connection.")
        connection.state = ClosedState()

class TCPConnection:
    def __init__(self):
        self.state = ClosedState()

    def open(self):
        self.state.open(self)

    def close(self):
        self.state.close(self)

# Usage
conn = TCPConnection()
conn.open()
conn.open()
conn.close()
conn.close()
Output
Opening connection. Connection already open. Closing connection. Connection already closed.
🎯

When to Use Which

Choose Strategy when you want to select from multiple algorithms or behaviors dynamically and independently of an object's state. It is ideal when you want to swap or extend algorithms without changing the context.

Choose State when an object's behavior depends on its internal state and you want the object to change behavior automatically as its state changes. It is best when you need to model complex state transitions and encapsulate state-specific behavior.

Key Takeaways

Strategy pattern encapsulates interchangeable algorithms and lets clients choose them dynamically.
State pattern manages behavior changes based on an object's internal state and state transitions.
Strategy promotes loose coupling by separating algorithms from context; State tightly couples state and behavior.
Use Strategy for flexible algorithm selection; use State for modeling state-dependent behavior.
Both patterns use composition and polymorphism but serve different design intents.