Шаблон проектирования Strategy
Шаблон проектирования Strategy относится к поведенческим паттернам и используется для выбора алгоритма во время исполнения программы динамически. Этот шаблон позволяет изменять поведение объекта путем изменения используемого алгоритма без изменения структуры класса.
Суть стратегии
Основная идея состоит в выделении различных вариантов поведения (алгоритмов) в отдельные классы, называемые стратегиями, и предоставлении возможности объекту выбрать подходящую стратегию во время выполнения программы.
Таким образом, объекты становятся гибкими и легко адаптируемыми к изменениям требований, так как разные реализации одного и того же функционала представлены отдельными классами, между которыми можно переключаться динамически.
Основные элементы паттерна
Паттерн включает три основных компонента:
1. Интерфейс Стратегии (Strategy
)
Интерфейс определяет общую сигнатуру метода, который реализует каждый алгоритм.
interface PaymentStrategy {
public function pay(float $amount): void;
}
2. Конкретная стратегия (ConcreteStrategy
)
Это реализация интерфейса PaymentStrategy
, представляющая отдельный алгоритм оплаты.
Например, различные способы оплаты:
class CreditCardPayment implements PaymentStrategy {
private string $cardNumber;
public function __construct(string $cardNumber) {
$this->cardNumber = $cardNumber;
}
public function pay(float $amount): void {
echo "Оплата кредитной картой №$this->cardNumber на сумму $amount.\n";
}
}
class PayPalPayment implements PaymentStrategy {
private string $email;
public function __construct(string $email) {
$this->email = $email;
}
public function pay(float $amount): void {
echo "Оплата через PayPal ($this->email) на сумму $amount.\n";
}
}
3. Контекст (Context
)
Контекст хранит ссылку на выбранную стратегию и делегирует ей выполнение соответствующей операции.
class ShoppingCart {
private PaymentStrategy $paymentStrategy;
public function setPaymentStrategy(PaymentStrategy $strategy): void {
$this->paymentStrategy = $strategy;
}
public function checkout(float $totalAmount): void {
if (!isset($this->paymentStrategy)) {
throw new Exception("Стратегия платежа не установлена.");
}
$this->paymentStrategy->pay($totalAmount);
}
}
Пример использования
Теперь рассмотрим пример полного сценария:
// Создаем корзину покупок
$cart = new ShoppingCart();
// Выбираем способ оплаты кредиткой
$creditCardPayment = new CreditCardPayment('1234-5678-9012');
$cart->setPaymentStrategy($creditCardPayment);
// Оплачиваем покупку
$cart->checkout(100); // Оплата кредитной картой №1234-5678-9012 на сумму 100.
// Меняем способ оплаты на PayPal
$paypalPayment = new PayPalPayment('example@example.com');
$cart->setPaymentStrategy($paypalPayment);
// Повторно оплачиваем покупку другим способом
$cart->checkout(100); // Оплата через PayPal (example@example.com) на сумму 100.
Преимущества использования паттерна Strategy:
- Гибкость: Возможность менять реализацию конкретного алгоритма во время выполнения программы.
- Расширяемость: Легко добавлять новые варианты поведения без изменений существующего кода.
- Улучшение читаемости и сопровождения: Каждая стратегия изолирована и имеет ясное назначение.
Этот паттерн часто применяется там, где необходимо выбирать одну из нескольких альтернативных реализаций одной и той же функциональности, обеспечивая высокую степень абстракции и возможность расширения приложения без переписывания основной логики.