Published on

[Behavioral] Strategy Pattern

The Strategy Design Pattern is a behavioral design pattern that enables selecting an algorithm or behavior at runtime.


๐Ÿง  Intent

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.


๐Ÿ”ง When to Use

  • You have multiple related algorithms or behaviors.
  • You want to switch between them dynamically.
  • You want to avoid conditional logic (if/elif or switch) for choosing behavior.
  • You want to isolate implementation details of algorithms from the context (client code).

๐Ÿ“Œ Structure

Context
 โ””โ”€โ”€ uses a Strategy

Strategy (Interface)
 โ”œโ”€โ”€ + algorithm_interface()
     โ–ฒ
     โ”‚
ConcreteStrategyA / ConcreteStrategyB
 โ””โ”€โ”€ implements algorithm_interface()

๐Ÿ Python Example

from abc import ABC, abstractmethod

# Strategy interface
class SortStrategy(ABC):
    @abstractmethod
    def sort(self, data):
        pass

# Concrete strategies
class BubbleSort(SortStrategy):
    def sort(self, data):
        print("Using Bubble Sort")
        return sorted(data)  # Placeholder

class QuickSort(SortStrategy):
    def sort(self, data):
        print("Using Quick Sort")
        return sorted(data)  # Placeholder

# Context
class Sorter:
    def __init__(self, strategy: SortStrategy):
        self.strategy = strategy

    def set_strategy(self, strategy: SortStrategy):
        self.strategy = strategy

    def sort(self, data):
        return self.strategy.sort(data)

# Usage
data = [5, 2, 9, 1]

sorter = Sorter(BubbleSort())
print(sorter.sort(data))  # Using Bubble Sort

sorter.set_strategy(QuickSort())
print(sorter.sort(data))  # Using Quick Sort

โœ… Benefits

  • Clean separation of concerns.
  • Open/Closed Principle (add new strategies without modifying context).
  • Replaces complex conditional logic with polymorphism.

โš ๏ธ Drawbacks

  • Increases number of classes.
  • Client must understand different strategies to choose one.

Real world example

Consider the example of sorting, we implemented bubble sort but the data started to grow and bubble sort started getting very slow. In order to tackle this we implemented Quick sort. But now although the quick sort algorithm was doing better for large datasets, it was very slow for smaller datasets. In order to handle this we implemented a strategy where for small datasets, bubble sort will be used and for larger, quick sort.

In plain words

Strategy pattern allows you to switch the algorithm or strategy based upon the situation.

Wikipedia says

In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables an algorithm's behavior to be selected at runtime.

Programmatic example

Translating our example from above. First of all we have our strategy interface and different strategy implementations

interface SortStrategy {
    sort(dataset: number[]): number[];
}

class BubbleSortStrategy implements SortStrategy {
    sort(dataset: number[]): number[] {
        console.log('Sorting using bubble sort')

        return dataset
    }
}

class QuickSortStrategy implements SortStrategy {
    sort(database: number[]): number[] {
        console.log('Sorting using quick sort')
        return database
    }
}

And then we have our client that is going to use any strategy

class Sorter {
    protected sorter;

    constructor(sorter: SortStrategy) {
        this.sorter = sorter
    }

    sort(dataset: number[]): number[] {
        return this.sorter.sort(dataset)
    }
}

And it can be used as

test('test strategy', () => {
    const dataset = [1, 5, 4, 3, 2, 8]

    let sorter = new Sorter(new BubbleSortStrategy())
    sorter.sort(dataset)

    sorter = new Sorter(new QuickSortStrategy())
    sorter.sort(dataset)
})

References