Behavioral Pattern

Strategy

Define a family of algorithms, encapsulate each one, and make them interchangeable so the algorithm can vary independently of the clients that use it.

Swappable algorithms.

The Strategy pattern lets you pick how something is done at runtime by plugging in different interchangeable algorithms. A navigation app has one Route interface and separate strategies for driving, walking, and cycling — you swap the strategy to change the behavior.

bad.py
# Problem: shipping rules jammed into one method with conditionals.
def shipping_cost(cart, method):
    if method == "ground":
        return cart.weight * 0.5
    elif method == "air":
        return cart.weight * 2.0
    elif method == "pickup":
        return 0
    # new method => edit + risk regressions
good.py
# Fix: Strategy — each algorithm is a swappable object.
from abc import ABC, abstractmethod

class Shipping(ABC):
    @abstractmethod
    def cost(self, cart): ...

class Ground(Shipping):
    def cost(self, cart): return cart.weight * 0.5

class Air(Shipping):
    def cost(self, cart): return cart.weight * 2.0

class Pickup(Shipping):
    def cost(self, cart): return 0

class Checkout:
    def __init__(self, shipping: Shipping):
        self.shipping = shipping          # inject strategy

    def total(self, cart):
        return cart.subtotal + self.shipping.cost(cart)

Checkout(Air()).total(cart)               # swap strategy without if/elif

Composition and OCP.

Participants: a Strategy interface, ConcreteStrategies, and a Context that holds a strategy and delegates work to it. The context doesn't know which algorithm it's using — just the interface.

  • Replaces conditionals — turns a big if/switch over "which algorithm" into polymorphic strategy objects.
  • Open/Closed — add a new algorithm by adding a strategy, not editing the context.
  • Runtime flexibility — swap behavior without changing the client.

Relations and trade-offs.

  • vs Template Method — Strategy varies a whole algorithm via composition (delegation); Template Method varies steps via inheritance (subclass hooks).
  • vs State — same structure, different intent: State transitions between behaviors based on internal state; Strategy is chosen by the client and usually doesn't self-transition.
  • Functional form — in languages with first-class functions/lambdas, a strategy is often just a function passed in, no interface/class needed.
  • Downsides — clients must know the strategies to choose among them, and many tiny strategy classes can add overhead.