Skip to content
patterns questions

Patterns · 8 of 10senior~2 min

What is the Strategy pattern and when would you use it?

#design-patterns#behavioral

Strategy Pattern

The strategy pattern defines a family of algorithms, puts each in a separate function/class, and makes them interchangeable. The context uses one strategy at a time without knowing the details.

Classic example - sorting

ts
type SortStrategy<T> = (items: T[]) => T[]; const byName: SortStrategy<User> = (users) => [...users].sort((a, b) => a.name.localeCompare(b.name)); const byAge: SortStrategy<User> = (users) => [...users].sort((a, b) => a.age - b.age); const byCreatedAt: SortStrategy<User> = (users) => [...users].sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()); // context - doesn't know which strategy is used function UserList({ users, sortBy }: { users: User[]; sortBy: SortStrategy<User> }) { const sorted = sortBy(users); return sorted.map(u => <UserRow key={u.id} user={u} />); } <UserList users={users} sortBy={byName} /> <UserList users={users} sortBy={byAge} />

Validation strategies

ts
type Validator = (value: string) => string | null; // null = valid const required: Validator = (v) => v.trim() ? null : 'Required'; const email: Validator = (v) => /^[^@]+@[^@]+$/.test(v) ? null : 'Invalid email'; const minLength = (n: number): Validator => (v) => v.length >= n ? null : `Min ${n} characters`; function validate(value: string, validators: Validator[]): string[] { return validators.map(v => v(value)).filter(Boolean) as string[]; } validate(input, [required, email, minLength(5)]);

Payment strategies

ts
interface PaymentStrategy { pay(amount: number): Promise<{ success: boolean; transactionId: string }>; } class StripeStrategy implements PaymentStrategy { async pay(amount: number) { return stripe.charge(amount); } } class PayPalStrategy implements PaymentStrategy { async pay(amount: number) { return paypal.transfer(amount); } } class Checkout { constructor(private strategy: PaymentStrategy) {} async process(amount: number) { return this.strategy.pay(amount); } } const checkout = new Checkout(new StripeStrategy());

Strategy is one of the most useful patterns in everyday frontend code. Any time you have if (type === 'x') ... else if (type === 'y') ... for behavior selection, you likely want a strategy map instead.

updated

did you know it?

related questions