Lesson 16 / 25

Strategy and Functions as Strategies

Interchangeable algorithms behind one interface.

Pick the algorithm at runtime

Intent: define a family of algorithms, encapsulate each one, and make them interchangeable so the client can choose at runtime. Shipping cost rules, pricing and discount rules, sorting or ranking policies, retry back-off policies and compression formats are typical. Strategy replaces growing if/else or switch chains spread across a codebase with a single variation point. In languages with first-class functions, a strategy is usually just a function with a known signature, and a map of name to function replaces the class hierarchy; classes still make sense when a strategy holds configuration or several related methods. Avoid it for one algorithm with no realistic alternatives.

Swap, notify and encapsulate actions

Behavioural patterns organise how objects share work and communicate.

Three ideas: interchangeable algorithms, event notification, actions as objects.
Figure 6.1 — Strategy, observer and command.

Shipping cost strategies as functions

A typed function signature is the interface.

type ShippingStrategy = (order: { weightKg: number; subtotalCents: number; country: string }) => number;

const flatRate: ShippingStrategy = () => 499;

const byWeight: ShippingStrategy = ({ weightKg }) => 299 + Math.ceil(weightKg) * 150;

const freeOverThreshold = (thresholdCents: number, fallback: ShippingStrategy): ShippingStrategy =>
  (order) => (order.subtotalCents >= thresholdCents ? 0 : fallback(order));

const strategies: Record<string, ShippingStrategy> = {
  standard: byWeight,
  flat: flatRate,
  promo: freeOverThreshold(5_000, byWeight),
};

function shippingCost(order: Order, method: string): number {
  const strategy = strategies[method];
  if (!strategy) throw new Error(`Unknown shipping method: ${method}`);
  return strategy(order);
}

Strategy is everywhere in standard libraries

Passing a comparator to Array.prototype.sort or a key function to Python's sorted is the Strategy pattern in its lightest form.

Quick check: In TypeScript, what is often the simplest form of a Strategy?

  • A deep inheritance hierarchy
  • A Singleton class
  • A function with a known signature, chosen from a map
  • A global mutable variable
Answer

A function with a known signature, chosen from a map — First-class functions replace many strategy classes.