Skip to main content

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
🔍 Three Implementation Approaches:
  • 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 QuickSort
Form 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);
  }
}