PHP — Strategy Design Pattern
I. What It Is?
- Strategy pattern is a behavioral design pattern that enables selecting an algorithm at runtime.
- Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
Type: Behavioral
II. Strategy Pattern in PHP
The Strategy pattern in PHP follows the same principles as in other programming languages. It is a behavioral design pattern that allows you to define a family of algorithms, encapsulate each one, and make them interchangeable. This way, the algorithm can vary independently from the clients that use it.
Here is an example of how you can implement the Strategy pattern in PHP:
interface PaymentStrategy {
public function pay($amount);
}
class CreditCardPayment implements PaymentStrategy {
public function pay($amount) {
echo "Paying $amount using Credit Card.\n";
}
}
class PayPalPayment implements PaymentStrategy {
public function pay($amount) {
echo "Paying $amount using PayPal.\n";
}
}
class BitcoinPayment implements PaymentStrategy {
public function pay($amount) {
echo "Paying $amount using Bitcoin.\n";
}
}
class PaymentContext {
private $paymentStrategy;
public function __construct(PaymentStrategy $paymentStrategy) {
$this->paymentStrategy = $paymentStrategy;
}
public function setPaymentStrategy(PaymentStrategy $paymentStrategy) {
$this->paymentStrategy = $paymentStrategy;
}
public function pay($amount) {
$this->paymentStrategy->pay($amount);
}
}
// Client code
$amount = 100;
// Example of selecting the strategy at runtime based on a condition
$paymentMethod = 'paypal'; // This could come from user input or some other runtime condition
switch ($paymentMethod) {
case 'creditcard':
$paymentStrategy = new CreditCardPayment();
break;
case 'paypal':
$paymentStrategy = new PayPalPayment();
break;
case 'bitcoin':
$paymentStrategy = new BitcoinPayment();
break;
default:
throw new Exception("Unknown payment method");
}
$paymentContext = new PaymentContext($paymentStrategy);
$paymentContext->pay($amount);
// Changing strategy at runtime
$paymentContext->setPaymentStrategy(new BitcoinPayment());
$paymentContext->pay($amount);
Explanation:
- PaymentStrategy Interface: Defines the method that all concrete strategies must implement.
- Concrete Strategies: Implement the
PaymentStrategy
interface with different algorithms for payment. - PaymentContext Class: Maintains a reference to a
PaymentStrategy
object and delegates the payment process to the current strategy. - Client Code: Uses the
PaymentContext
to perform payments and can change the strategy at runtime.
- Runtime Selection: The
switch
statement determines which payment strategy to use based on the value of$paymentMethod
. This value could be set dynamically at runtime, for example, based on user input. - Changing Strategy: The
PaymentContext
can change its strategy at any time by calling thesetPaymentStrategy
method with a new strategy.
This demonstrates the flexibility of the Strategy pattern, as it allows the algorithm to vary independently from the clients that use it. The actual algorithm can be chosen and changed dynamically at runtime, making the code more flexible and easier to maintain.
III. Practical Applications
- Payment Processing:
- Scenario: You have an e-commerce platform that needs to handle multiple payment gateways like PayPal, Stripe, and bank transfers.
- Implementation: Implement each payment gateway as a concrete strategy that follows a
PaymentGateway
interface. The application dynamically selects the appropriate payment strategy based on user input.
2. Sorting Algorithms:
- Scenario: A data processing tool needs to support different sorting algorithms like quicksort, mergesort, and bubblesort.
- Implementation: Create a
SortStrategy
interface that different sorting algorithms implement. The application can switch between sorting strategies at runtime based on data size and sorting speed requirements.
3. Logging Mechanisms:
- Scenario: A system needs to log messages to various backends like files, databases, or cloud logging services.
- Implementation: Define a
LoggerStrategy
interface that different logging strategies implement. The main logger dynamically selects the appropriate strategy based on configuration settings.
4. Compression:
- Scenario: A file management system needs to compress files using different algorithms like ZIP, GZIP, or BZIP2.
- Implementation: Implement a
CompressionStrategy
interface with different concrete strategies for each compression algorithm. The file management system selects a compression strategy based on user preferences or file size.
5. Validation Rules:
- Scenario: A data validation service needs to apply different validation rules based on the type of data being validated (e.g., emails, URLs, or phone numbers).
- Implementation: Create a
ValidationStrategy
interface that each concrete validation rule implements. The service can then switch validation strategies dynamically based on the type of data being processed.