🎯 Strategy Pattern
✅ What You’ll Learn
- What the Strategy Pattern is
- When and why to use it
- How to implement it in Python
- Benefits of using it
- Common use cases
📘 What is the Strategy Pattern?
Strategy Pattern is a behavioral design pattern that lets you define a family of algorithms, put each of them in a separate class, and make their objects interchangeable.
It allows the behavior of a class to change at runtime without modifying its code.
🧠 When to Use It
Use the Strategy Pattern when:
- You have multiple algorithms for a specific task.
- You want to swap the algorithms at runtime.
- You want to avoid massive if-else or switch-case statements.
- You want to follow the Open/Closed Principle: open for extension, closed for modification.
📊 UML Diagram Description
Imagine you’re building a program that needs to sort data, and you want to:
- Allow different sorting algorithms (BubbleSort, QuickSort, MergeSort…)
- Choose or change the algorithm at runtime
- Keep your sorting system extendable
This diagram shows how to organize your classes to achieve all of that.
classDiagram
class Strategy {
<<interface>>
+do_algorithm(data)
}
class BubbleSortStrategy {
+do_algorithm(data)
}
class QuickSortStrategy {
+do_algorithm(data)
}
class Context {
-strategy: Strategy
+set_strategy(strategy: Strategy)
+execute_strategy(data)
}
Strategy <|.. BubbleSortStrategy
Strategy <|.. QuickSortStrategy
Context --> Strategy
🧭 Diagram Breakdown
🧩 1. Strategy Interface (Abstraction)
- This is the common interface or abstract base class.
- It declares a method do_algorithm(data) that all concrete strategies must implement.
- This abstraction allows different strategies to be interchangeable.
🧩 2. BubbleSortStrategy and QuickSortStrategy (Concrete Strategies)
- These implement the Strategy interface.
- Each provides a specific version of the do_algorithm() method.
- Example: Bubble sort and quick sort are two ways to sort a list, and they’re swappable.
🧩 3. Context Class
- Holds a reference to a Strategy object.
- Delegates the algorithm execution to the Strategy via execute_strategy(data).
- Can dynamically change the strategy using set_strategy().
Context depends on Strategy but doesn’t implement or extend it.
🛠️ 4. Implementation of Strategy Pattern in Python
Step 1: Define the Strategy Interface (using Abstract Base Class)
from abc import ABC, abstractmethod
class Strategy(ABC):
@abstractmethod
def do_algorithm(self, data):
pass
Step 2: Implement Concrete Strategies
class BubbleSortStrategy(Strategy):
def do_algorithm(self, data):
print("Using Bubble Sort")
return sorted(data) # Simulating bubble sort for simplicity
class QuickSortStrategy(Strategy):
def do_algorithm(self, data):
print("Using Quick Sort")
return sorted(data) # Simulating quick sort for simplicity
Step 3: Create the Context
class Context:
def __init__(self, strategy: Strategy):
self._strategy = strategy
def set_strategy(self, strategy: Strategy):
self._strategy = strategy
def execute_strategy(self, data):
return self._strategy.do_algorithm(data)
Step 4: Use It
if __name__ == "__main__":
data = [5, 3, 9, 1]
context = Context(BubbleSortStrategy())
print(context.execute_strategy(data)) # Using Bubble Sort
context.set_strategy(QuickSortStrategy())
print(context.execute_strategy(data)) # Using Quick Sort
✅ Output
Using Bubble Sort
[1, 3, 5, 9]
Using Quick Sort
[1, 3, 5, 9]
🚀 Benefits of Strategy Pattern
- Flexibility: Swap algorithms without changing the context.
- Clean Code: Avoid long if-else or switch statements.
- Reusability: Strategies can be reused in different contexts.
- Testability: You can test strategies in isolation.
🔥 Real-world Use Cases
- Sorting algorithms (as above)
- Payment methods (CreditCard, PayPal, ApplePay)
- Compression strategies (Zip, Rar, Tar)
- Pathfinding algorithms (Dijkstra, A*, BFS)
- Game AI behaviors
📌 Advanced Tip: Use Functions as Strategies (Pythonic Way)
You can also use first-class functions as strategies:
def bubble_sort(data):
print("Function Bubble Sort")
return sorted(data)
def quick_sort(data):
print("Function Quick Sort")
return sorted(data)
class FunctionContext:
def __init__(self, strategy_func):
self._strategy_func = strategy_func
def set_strategy(self, strategy_func):
self._strategy_func = strategy_func
def execute(self, data):
return self._strategy_func(data)
ctx = FunctionContext(bubble_sort)
print(ctx.execute([3, 1, 4]))
ctx.set_strategy(quick_sort)
print(ctx.execute([3, 1, 4]))
📚 Summary
Component | Role |
---|---|
Strategy | Interface for algorithms |
ConcreteStrategy | Actual implementations |
Context | Uses the strategy |