Strategy Pattern - Interchangeable Algorithms in TypeScript
Master the Strategy pattern for defining interchangeable algorithms. TypeScript examples for sorting, validation, pricing, and authentication strategies.
Detailed Explanation
Strategy Pattern
The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. The algorithm can vary independently from the clients that use it.
Without Strategy
Code without Strategy often contains large switch statements or if-else chains:
// Before: brittle, violates Open/Closed Principle
function calculateShipping(method: string, weight: number) {
if (method === "ground") return weight * 1.5;
if (method === "air") return weight * 3.0;
if (method === "express") return weight * 5.0;
throw new Error("Unknown method");
}
With Strategy
interface ShippingStrategy {
calculate(weight: number): number;
name: string;
}
class GroundShipping implements ShippingStrategy {
name = "Ground";
calculate(weight: number) { return weight * 1.5; }
}
class AirShipping implements ShippingStrategy {
name = "Air";
calculate(weight: number) { return weight * 3.0; }
}
class ShippingCalculator {
constructor(private strategy: ShippingStrategy) {}
setStrategy(s: ShippingStrategy) { this.strategy = s; }
calculate(weight: number) { return this.strategy.calculate(weight); }
}
Strategy vs State
Both patterns use composition and delegation. The difference is intent: Strategy lets the client choose the algorithm; State manages internal transitions automatically. Strategy objects are often stateless and interchangeable; State objects carry context about the current state.
Functional Alternative
In languages with first-class functions (TypeScript, JavaScript, Python), the Strategy pattern can be simplified to passing a function:
type PricingFn = (base: number) => number;
const premium: PricingFn = (base) => base * 0.9;
const standard: PricingFn = (base) => base;
This functional approach works well for simple strategies but loses the ability to carry state or implement multiple methods.
Use Case
Strategy is ideal for payment processing (switching between Stripe, PayPal, bank transfer), file compression (gzip, brotli, zstd), authentication methods (OAuth, JWT, API key), sorting algorithms in visualization tools, and any scenario where the algorithm should be selected at runtime.