The Strategy Pattern

2026-04-21

The Strategy pattern lets you swap an algorithm at runtime without changing the code that uses it. You define a family of interchangeable behaviors behind a common interface, then inject the one you need. It eliminates conditional chains that grow every time you add a new variant.

The problem it solves: You have a function with a growing if/else or switch block that selects behavior based on type. Every new variant means modifying that function, violating the Open-Closed Principle. The Strategy pattern inverts this — new behavior means adding a new class, not editing existing code.

Real-world example: payment processing. Suppose your checkout service supports credit cards, PayPal, and bank transfers. The naive approach:

Every new payment method touches this function. With Strategy, you define a PaymentStrategy interface with a charge(amount) method, then implement CreditCardStrategy, PayPalStrategy, and BankTransferStrategy. Your checkout service receives a strategy and calls strategy.charge(amount) — it never knows or cares which one it got.

Adding Apple Pay? Write ApplePayStrategy, register it in your factory or DI container, and the checkout service stays untouched. Zero modifications to existing, tested code.

When to apply it — the Rule of Three: If you have three or more variants of the same behavior, extract a strategy. Two variants rarely justify the abstraction. Three means the pattern is growing and will likely grow more. This is a practical threshold — premature abstraction at two variants often creates indirection without payoff.

Implementation tips:

Testing benefit: Each strategy is a small, isolated unit. You test CreditCardStrategy.charge() independently, then test that your checkout service correctly delegates — without needing integration tests for every payment method.

Common mistake: Over-applying it. If the behavior genuinely won't vary, a plain function is fine. Patterns exist to manage complexity, not to create it. A strategy with one implementation is just indirection.

See it in action: Check out Strategy Pattern, The Best Software Design Pattern by Jono Williams to see this theory applied.
Key Takeaway: Use the Strategy pattern to replace growing conditional branches with interchangeable, independently testable behavior classes — apply it once you hit three or more variants.