All topics
Patternsintermediate

Strategy Pattern

Encapsulating interchangeable algorithms or behaviors behind a common interface so they can be swapped at runtime without changing the code that uses them.

The Strategy pattern defines a family of interchangeable algorithms or behaviors, encapsulates each one separately behind a common interface, and lets the calling code select and swap between them at runtime, rather than hardcoding a single fixed algorithm or scattering conditional branches (if/else or switch chains) throughout the consuming code every time a variant is needed. It's a very natural fit for JavaScript specifically, since functions are first-class values, so 'a strategy' is often literally just a plain function passed around, without needing the more ceremonial interface/class-based structure the pattern requires in stricter, more rigid OOP languages.

The Strategy pattern is like a GPS navigation app offering several route-calculation modes — fastest, shortest, avoid tolls — where the app's core turn-by-turn guidance logic doesn't care which specific mode you picked, it just plugs whichever route-calculation strategy you selected into the same guidance system, and adding a brand-new 'scenic route' mode later doesn't require touching the guidance engine itself at all.

Key Concepts

1
A classic use case is a pricing or discount calculation that varies based on context — a calculateDiscount(strategy, price) function that receives whichever discount strategy function applies to the current situation (regular customer, loyalty member, holiday sale), and simply calls it, without needing to know or care which specific strategy it received or how that strategy computes its result internally. Adding a brand-new discount strategy later means writing one new function and passing it in at the appropriate call site — the calculateDiscount function itself never needs to change, since it was never aware of the specific strategies to begin with, only the common shape (a function taking a price and returning a discounted price) they all share.
calculateDiscount(strategy, price)calculateDiscount
2
This pattern directly relates to the higher-order-function concept covered elsewhere — in JavaScript, the Strategy pattern is often indistinguishable from simply 'passing a function as an argument,' and many developers use it without necessarily naming it as a formal design pattern at all. The value of recognizing it explicitly as a pattern is mostly about intentionality: naming the technique helps you notice when a growing pile of if/else branches handling different 'modes' of behavior could instead be refactored into a lookup table or object mapping names to strategy functions, entirely eliminating the branching logic in favor of a single dynamic function call (strategies[selectedStrategy](args)).
if/elsestrategies[selectedStrategy](args)
3
Compared to the factory pattern (which is about *creating objects*), Strategy is specifically about swapping *behavior/algorithms* — the two patterns are sometimes used together, where a factory decides which strategy object/function to construct based on some input, and the calling code then applies whichever strategy the factory handed back.