The Strategy Pattern is a behavioral design pattern that enables an object to change its behavior at runtime.
This pattern is particularly useful when you want to rewrite a part of a class from outside. It lets you define a family of similar algorithms, each in a separate class, and make them interchangeable.
The primary components of this pattern are:
- Context: The class that interacts with a strategy interface to perform a task.
- Strategy Interface: This interface defines a common set of behaviors that are implemented by all supported algorithms.
- Concrete Strategies: These classes implement the strategy interface with specific algorithms.
Example
A typical example that can demonstrate the strategy pattern is a payment service with multiple payment methods that can be implemented as different strategies:
// The Strategy Interface
interface PaymentMethod {
public function pay(int $amount): void;
}// Concrete Strategies
class PayPal implements PaymentMethod {
public function pay(int $amount): void {
echo "Paying $amount using PayPal\n";
}
}
class CreditCard implements PaymentMethod {
public function pay(int $amount): void {
echo "Paying $amount using Credit Card\n";
}
}// The Context
class ShoppingCart {
/** @var list<int> */
private array $items = [];
public function __construct(
private PaymentMethod $paymentMethod,
) {}
public function addItem(int $item): void {
$this->items[] = $item;
}
public function setPaymentMethod(PaymentMethod $paymentMethod): void {
$this->paymentMethod = $paymentMethod;
}
public function checkout(): void {
$amount = array_sum($this->items);
$this->paymentMethod->pay($amount);
}
}// Can use different payment strategies interchangeably
$cart = new ShoppingCart(new PayPal());
$cart->addItem(100);
$cart->addItem(200);
// Paying with PayPal
$cart->checkout();
// Paying with Credit Card
$cart->setPaymentMethod(new CreditCard());
$cart->checkout();Advantages
- Flexibility: Allows for easy switching between different algorithms or strategies.
- Loose Coupling: The context class is independent of how the strategy is implemented.
- Extensibility: Adding new strategies does not require changing the context.
Although simple to implement, the benefits of the Strategy Pattern are huge. It implements both the Single Responsibility principle and the Open-Closed principle, offering significant flexibility and scalability in software design with minimal complexity.