Strategy
Swap algorithms at runtime behind a common interface.
8 min read · lesson 26 of 41
Strategy puts each variant of an algorithm in its own class behind a shared interface, so the code that uses the algorithm can swap it without changing. It's the single most useful pattern in LLD interviews.
The idea
To get to the airport you can take a cab, the metro, or drive. The goal is the same; the method differs by budget, time, and traffic. A navigation app lets you pick the strategy and computes the route accordingly, without rewriting the app for each mode.
Context ──────> <<interface>> Strategy (uses one) + execute() ▲ ▲ ▲ StratA StratB StratCWhy it matters
Whenever an interviewer says "different pricing for weekends", "multiple payment methods", "several matching algorithms", or "different eviction policies", they're inviting a Strategy. It:
- Replaces conditionals with polymorphism (Open/Closed).
- Isolates each algorithm for testing.
- Allows runtime selection, from config or per request.
from abc import ABC, abstractmethodfrom dataclasses import dataclassfrom datetime import datetime@dataclass(frozen=True)class Ticket: vehicle_type: str entry: datetimeclass PricingStrategy(ABC): @abstractmethod def fee(self, ticket: Ticket, exit_time: datetime) -> int: ...class HourlyPricing(PricingStrategy): RATES = {"bike": 20, "car": 50, "truck": 100} def fee(self, ticket: Ticket, exit_time: datetime) -> int: hours = max(1, -(-int((exit_time - ticket.entry).total_seconds()) // 3600)) return hours * self.RATES[ticket.vehicle_type]class FlatEventPricing(PricingStrategy): def __init__(self, flat: int) -> None: self.flat = flat def fee(self, ticket: Ticket, exit_time: datetime) -> int: return self.flatclass ExitGate: def __init__(self, pricing: PricingStrategy) -> None: self._pricing = pricing def set_pricing(self, pricing: PricingStrategy) -> None: self._pricing = pricing # swap at runtime, e.g. on event days def checkout(self, ticket: Ticket, now: datetime) -> int: return self._pricing.fee(ticket, now)t = Ticket("car", datetime(2026, 10, 9, 9, 0))gate = ExitGate(HourlyPricing())print(gate.checkout(t, datetime(2026, 10, 9, 11, 30))) # 150gate.set_pricing(FlatEventPricing(300))print(gate.checkout(t, datetime(2026, 10, 9, 11, 30))) # 300In Python, a strategy with one method can also just be a function (Callable[[Ticket, datetime], int]). Use a class when the strategy has configuration or more than one method.
When to use / when not to
Use Strategy for any family of interchangeable algorithms: pricing, fare calculation, spot allocation, driver matching, elevator scheduling, cache eviction, rate-limiting algorithms, split types in Splitwise. Don't use it when there's only one algorithm and no hint of variation, or when the variants differ only by a number (a field will do).
Common mistakes
- Still switching on type to select the strategy deep inside business logic; pick it once via a factory or config.
- Strategies that need access to lots of context internals; pass what they need explicitly.
- Confusing Strategy with State: in State, the object switches its own behaviour as its status changes; in Strategy, the client chooses.
- Creating strategy classes where a lambda or function is clearer.
In the interview
Q: Strategy vs State? Same structure, different intent. Strategy is chosen from outside and represents how to do something; State changes internally as the object moves through its lifecycle and represents what mode it's in.
Q: How do you choose the strategy at runtime? A factory or registry keyed by configuration or request input, invoked once at the boundary, and the strategy is injected into the context.
Q: Strategy vs Template Method? Strategy uses composition to swap the whole algorithm; Template Method uses inheritance to vary steps within a fixed skeleton. Strategy is usually more flexible.
Key takeaways
- Strategy = interchangeable algorithms behind one interface, chosen by the client.
- It's the default answer to "what if we add another way to do X?".
- Select the strategy once at the boundary; inject it.
- In Python, single-method strategies can be plain functions.