Skip to content

Strategy

Strategy defines a family of algorithms, puts each one behind a common interface, and makes them interchangeable. The object that needs the work delegates to a strategy chosen at runtime, so the algorithm can vary without touching the code that uses it.

Imagine a checkout that computes a final price. At first there is one rule. Then marketing adds a percentage discount for members, a flat coupon, a buy-one-get-one offer, and a seasonal sale. If all of this lives inside one method, it grows into a long chain of branches that you must reopen and re-test every time a new rule appears, and the pricing logic gets tangled with the order code around it.

The variation here is the pricing algorithm itself. Strategy isolates that axis: each rule becomes its own small object implementing a shared interface, and the order holds a reference to whichever one applies. Adding a rule means adding a class, not editing a conditional. Swapping the rule at runtime — member versus guest, sale versus normal — is just assigning a different strategy.

classDiagram
  class Context {
    -strategy: PricingStrategy
    +setStrategy(s)
    +priceFor(amount) number
  }
  class PricingStrategy {
    <<interface>>
    +apply(amount) number
  }
  class RegularPricing {
    +apply(amount) number
  }
  class MemberPricing {
    +apply(amount) number
  }
  class CouponPricing {
    +apply(amount) number
  }
  Context o--> PricingStrategy
  PricingStrategy <|.. RegularPricing
  PricingStrategy <|.. MemberPricing
  PricingStrategy <|.. CouponPricing
A Context delegates to one of several interchangeable PricingStrategy implementations
  • Strategy — the common interface that every algorithm implements. The context depends only on this.
  • Concrete Strategy — one implementation of the interface; here, each pricing rule.
  • Context — holds a reference to a strategy and delegates the work to it. It can be reconfigured with a different strategy at runtime.
  • Client — picks the concrete strategy and hands it to the context.

A pricing context that computes a final amount by delegating to an interchangeable pricing strategy. Each language expresses the strategy as whatever is idiomatic — an interface, a protocol, a function type, or a trait object.

interface PricingStrategy {
apply(amount: number): number;
}
class RegularPricing implements PricingStrategy {
apply(amount: number): number {
return amount;
}
}
class MemberPricing implements PricingStrategy {
apply(amount: number): number {
return amount * 0.9; // 10% off
}
}
class CouponPricing implements PricingStrategy {
constructor(private readonly off: number) {}
apply(amount: number): number {
return Math.max(0, amount - this.off);
}
}
class Checkout {
constructor(private strategy: PricingStrategy) {}
setStrategy(strategy: PricingStrategy): void {
this.strategy = strategy;
}
priceFor(amount: number): number {
return this.strategy.apply(amount);
}
}
const checkout = new Checkout(new RegularPricing());
console.log(checkout.priceFor(100)); // 100
checkout.setStrategy(new MemberPricing());
console.log(checkout.priceFor(100)); // 90
checkout.setStrategy(new CouponPricing(15));
console.log(checkout.priceFor(100)); // 85
  • Pro: swaps algorithms at runtime and adds new ones without editing the context or existing strategies.
  • Pro: replaces a sprawling conditional with small, individually testable units.
  • Pro: each strategy can be unit-tested in isolation, free of the surrounding context.
  • Con: introduces extra objects and an interface; for two trivial branches a plain if is simpler.
  • Con: the client must know enough to choose the right strategy, which moves a decision outward.
  • State has the same structure but a different intent — its objects swap themselves as state changes, rather than being chosen by the client.
  • Template Method varies an algorithm through inheritance and overridden steps, where Strategy varies it through composition.
What does the Strategy pattern make interchangeable?
How does a Context use a Strategy?
What is the main advantage over a large conditional?
How does Strategy differ from State?