What is the Strategy pattern and when would you use it?
The Strategy pattern is a behavioral design pattern that defines a family of algorithms, encapsulates each one, and makes them interchangeable. The key insight is that the algorithm is extracted from the context that uses it and placed behind an interface, so the context can switch algorithms at runtime without knowing the details of any specific implementation.
**Structure:** - **Context:** holds a reference to a Strategy object and delegates the work to it - **Strategy interface:** defines the method signature all concrete strategies must implement - **Concrete Strategies:** implement the algorithm variations
Python example (payment processing):
```python from abc import ABC, abstractmethod
class PaymentStrategy(ABC): @abstractmethod def charge(self, amount: float) -> bool: ...
class StripeStrategy(PaymentStrategy): def charge(self, amount: float) -> bool: # call Stripe API return True
class PayPalStrategy(PaymentStrategy): def charge(self, amount: float) -> bool: # call PayPal API return True
class Checkout: def __init__(self, payment: PaymentStrategy): self._payment = payment
def process(self, amount: float): if not self._payment.charge(amount): raise PaymentError('Charge failed') ```
The `Checkout` context doesn't know or care whether it's using Stripe or PayPal — it only calls `charge()`. Adding a new payment provider requires implementing the interface and injecting it, without modifying `Checkout`.
**When to use:** - You have multiple variations of an algorithm that differ only in behavior (sorting algorithms, compression codecs, pricing strategies, authentication mechanisms) - You want to eliminate conditionals that select algorithm variants (`if payment_type == 'stripe': ... elif payment_type == 'paypal': ...`) - You need to swap algorithms at runtime based on configuration or user selection - You want to test each algorithm in isolation
**Python-specific note:** In Python, first-class functions often replace full Strategy classes for simple cases. Passing a callable is idiomatic when the strategy has a single method:
```python def checkout(amount, charge_fn): return charge_fn(amount)
checkout(100.0, stripe_charge) # just pass the function ```
Full class-based Strategy is warranted when the strategy needs state (e.g., maintaining a connection) or multiple related methods.
The Open/Closed Principle is the direct motivation: the system is open for extension (new strategies) but closed for modification (context unchanged).
Correctly defines the pattern (interchangeable algorithms behind an interface), gives a concrete real-world example, and explains the elimination of conditionals as a motivation.
Covers structure (context/interface/concrete), real example, Open/Closed Principle connection, Python callable alternative for simple cases, and knows when class-based Strategy is warranted over simple callables.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment