The Strategy design 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.
In simple words:
-
You have different ways (strategies) of doing something.
-
Instead of hardcoding all those ways inside one big class, you encapsulate each way separately.
-
Then, at runtime, you can choose which strategy you want to use.
Key parts:
-
Context: the main object that uses a strategy.
-
Strategy Interface: common interface for all strategies (they must follow a contract).
-
Concrete Strategies: different implementations of the strategy.
Quick Example (Payment System):
-
Strategy Interface:
PaymentStrategy
with methodpay(amount)
. -
Concrete Strategies:
-
CreditCardPayment
-
PayPalPayment
-
CryptoPayment
-
-
Context:
ShoppingCart
that uses aPaymentStrategy
to pay.
So you can easily switch between paying with a credit card, PayPal, or crypto without changing the ShoppingCart
class.
Aspect | Strategy Pattern | Proxy Pattern | Template Method Pattern |
---|---|---|---|
Purpose | Select an algorithm at runtime. | Control access to another object (with additional functionality if needed). | Define the skeleton of an algorithm, letting subclasses fill in the specific steps. |
Main Idea | Swap different strategies (algorithms) easily. | Act as a substitute for another object to add control (like lazy loading, security, caching). | Keep the overall structure of an algorithm, but allow parts to be overridden. |
Example | Different payment methods: PayPal, credit card, crypto. | Virtual proxy for an image that loads only when needed. | Online order: steps like checkout, payment, and confirmation, but allow different payment processors to override parts. |
Pattern Type | Behavioral | Structural | Behavioral |
Flexibility | High — change behavior at runtime. | Medium — mainly adds a wrapper around existing objects. | Low — template is fixed; only certain parts are customizable. |
Key Participants | Context, Strategy Interface, Concrete Strategies | Proxy, Real Subject | Abstract Class (template), Concrete Subclasses |
One-liner Summaries:
-
Strategy = "Choose which behavior to use."
-
Proxy = "Control access to an object."
-
Template = "Define the steps, let subclasses fill in the blanks."
java implementation:
// Strategy Interface interface PaymentStrategy { void pay(int amount); } // Concrete Strategies class CreditCardPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid " + amount + " using Credit Card."); } } class PayPalPayment implements PaymentStrategy { public void pay(int amount) { System.out.println("Paid " + amount + " using PayPal."); } } // Context class ShoppingCart { private PaymentStrategy paymentStrategy; public void setPaymentStrategy(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; } public void checkout(int amount) { paymentStrategy.pay(amount); } } // Usage public class Main { public static void main(String[] args) { ShoppingCart cart = new ShoppingCart(); cart.setPaymentStrategy(new PayPalPayment()); cart.checkout(100); } }
python implementation:
from abc import ABC, abstractmethod # Strategy Interface class PaymentStrategy(ABC): @abstractmethod def pay(self, amount): pass # Concrete Strategies class CreditCardPayment(PaymentStrategy): def pay(self, amount): print(f"Paid {amount} using Credit Card.") class PayPalPayment(PaymentStrategy): def pay(self, amount): print(f"Paid {amount} using PayPal.") # Context class ShoppingCart: def __init__(self): self.payment_strategy = None def set_payment_strategy(self, strategy): self.payment_strategy = strategy def checkout(self, amount): self.payment_strategy.pay(amount) # Usage cart = ShoppingCart() cart.set_payment_strategy(PayPalPayment()) cart.checkout(100)
output:
0 Comments