Strategy Pattern
Encapsulate algorithms and make them interchangeable at runtime
Pattern Overview
🎭 The Strategy Pattern - Interchangeable Algorithms
Defines a family of algorithms, encapsulates each one, and makes them interchangeable at runtime!
- Core Problem Solved:
- Switch between different algorithms dynamically
- Eliminate complex conditional statements
- Support easy algorithm extension
- Decouple algorithm implementation from usage
- Interface-based: Traditional OOP with strategy interfaces
- Function-based: Modern functional approach with higher-order functions
- Class-based: Strategy classes with shared behavior
- Real-World Applications:
- Payment processing systems (credit card, PayPal, crypto)
- Sorting algorithms (quicksort, mergesort, heapsort)
- Form validation rules and strategies
- Data compression algorithms
- Routing and pathfinding algorithms
- Authentication mechanisms
- Modern Usage Examples:
- React form validation libraries
- Data processing pipelines
- Microservice routing strategies
- A/B testing algorithm selection
Examples:
Data processing - choose optimal sorting algorithm based on data size
Input:
sorter.setStrategy(new QuickSortStrategy())Output:
Strategy changed to QuickSortForm validation - apply different validation rules per field type
Input:
validator.validateField('email', 'user@example.com')Output:
{ isValid: true, errors: [] }E-commerce - handle different payment methods with varying fees
Input:
processor.processPayment('creditCard', 100)Output:
{ success: true, transactionId: 'cc_xyz', fee: 2.90 }Algorithm selection - same interface, different implementations
Input:
sorter.sort([3, 1, 4, 1, 5, 9, 2, 6])Output:
[1, 1, 2, 3, 4, 5, 6, 9]Concepts
Algorithm EncapsulationRuntime SelectionInterchangeable BehaviorPolicy PatternBehavioral Parameterization
Complexity Analysis
Time:Depends on chosen algorithm
Space:O(1) - strategy storage overhead
Implementation
DataSorter
Time: Varies by algorithm | Space: O(1)
// Strategy pattern for sorting algorithms
interface SortingStrategy {
sort(data: number[]): number[];
getName(): string;
getComplexity(): string;
}
class QuickSortStrategy implements SortingStrategy {
sort(data: number[]): number[] {
if (data.length <= 1) return [...data];
const pivot = data[Math.floor(data.length / 2)];
const less = data.filter(x => x < pivot);
const equal = data.filter(x => x === pivot);
const greater = data.filter(x => x > pivot);
return [
...this.sort(less),
...equal,
...this.sort(greater)
];
}
getName(): string {
return 'Quick Sort';
}
getComplexity(): string {
return 'O(n log n) average, O(n²) worst';
}
}
class DataSorter {
constructor(private strategy: SortingStrategy) {}
public setStrategy(strategy: SortingStrategy): void {
this.strategy = strategy;
}
public sort(data: number[]): number[] {
console.log(`Sorting with ${this.strategy.getName()}`);
return this.strategy.sort(data);
}
}