design·lab

Behavioral pattern

Strategy

A context needs to run one of several interchangeable algorithms — Strategy hides each one behind a common interface so the context never has to know which one it's running.

✗ The problem

A growing if/else picks the algorithm

Every new payment method means editing this one function again.

function checkout(amount, type) {
  if (type === 'card')   return amount * 1.029 + 0.30;
  if (type === 'paypal') return amount * 1.034;
  if (type === 'crypto') return amount + 1.00;
  // new method? reopen and edit this again…
}
All three algorithms are tangled inside one function — you can't test card math without dragging paypal and crypto along, and adding a fourth method means reopening code that already works.
✓ The pattern

Extract each algorithm behind one interface

The context holds a strategy object and just delegates to it. It has no idea which concrete algorithm is running.

class PaymentStrategy {
  pay(amount) { /* override me */ }
}

class CardStrategy extends PaymentStrategy {
  pay(amount) {
    return amount * 1.029 + 0.30;
  }
}

class Checkout {
  constructor(strategy) {
    this.strategy = strategy;
  }

  checkout(amount) {
    return this.strategy.pay(amount);
  }
}
Checkout
holds a strategy
PaymentStrategy
interface: pay(amount)
CardStrategy
PaypalStrategy
CryptoStrategy
Strategy is how you realize Open/Closed for interchangeable algorithms — a new payment method is a new class, not an edit to Checkout.
✓ See it live

Swap the algorithm at runtime

Pick a strategy, then run checkout on a fixed $100 charge. The Checkout context stays the same — only which strategy it holds changes.

💳 Card
2.9% + $0.30
🅿️ PayPal
3.4%
₿ Crypto
flat $1.00
Pick a strategy above, then pay

Tip: click another strategy and pay again — same amount, different fee.

✓ Takeaway

Interchangeable algorithms, no rewrites

  • Swap algorithms at runtime by handing the context a different strategy object.
  • Each strategy tested in isolation — no if/else chain to drag along.
  • Add a strategy = add a class. Checkout never changes (Open/Closed).
  • Careful: overkill for one stable algorithm that never varies — that's just YAGNI.
🎯 Principle applied: Strategy is how you get Open/Closed for algorithms — add a new strategy class without touching the context — and Dependency Inversion: the context depends on the PaymentStrategy interface, never a concrete algorithm. Each strategy is independently testable (SRP).