← Назад к вопросам

Когда применять паттерн проектирования Стратегия в PHP?

2.3 Middle🔥 112 комментариев
#Архитектура и паттерны#ООП

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Когда применять паттерн проектирования «Стратегия» в PHP

Паттерн Стратегия (Strategy) — это поведенческий паттерн проектирования, который определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Он позволяет изменять алгоритмы независимо от клиентов, которые их используют. В PHP этот паттерн особенно полезен в контексте динамически типизированного языка, где гибкость и расширяемость часто критичны.

Ключевые ситуации для применения

  1. Когда есть несколько вариантов одного алгоритма или поведения
    Если в системе существует несколько способов выполнения одной операции (например, различные алгоритмы сортировки, способы доставки, методы оплаты или форматы экспорта данных), Стратегия позволяет вынести каждый вариант в отдельный класс. Это избавляет от монолитных условных конструкций (if/else или switch).

    // Без стратегии
    class OrderProcessor {
        public function process($order, $paymentType) {
            if ($paymentType === 'credit_card') {
                // Обработка кредитной карты
            } elseif ($paymentType === 'paypal') {
                // Обработка PayPal
            } // ... и т.д.
        }
    }
    
    // Со стратегией
    interface PaymentStrategy {
        public function pay($amount);
    }
    
    class CreditCardPayment implements PaymentStrategy {
        public function pay($amount) { /* ... */ }
    }
    
    class PayPalPayment implements PaymentStrategy {
        public function pay($amount) { /* ... */ }
    }
    
    class OrderProcessor {
        private $paymentStrategy;
    
        public function setPaymentStrategy(PaymentStrategy $strategy) {
            $this->paymentStrategy = $strategy;
        }
    
        public function process($order) {
            $this->paymentStrategy->pay($order->amount);
        }
    }
    
  2. Когда необходимо динамически менять поведение объекта во время выполнения
    В отличие от наследования, которое фиксирует поведение на этапе компиляции (в PHP — на этапе определения класса), Стратегия позволяет подменять алгоритмы «на лету». Например, выбор способа кэширования (Redis, Memcached, файловый) в зависимости от текущей нагрузки или конфигурации.

    class CacheManager {
        private $cacheStrategy;
    
        public function __construct(CacheStrategy $strategy) {
            $this->cacheStrategy = $strategy;
        }
    
        public function setStrategy(CacheStrategy $strategy) {
            $this->cacheStrategy = $strategy;
        }
    
        public function get($key) {
            return $this->cacheStrategy->get($key);
        }
    }
    
    // Использование
    $cache = new CacheManager(new RedisCache());
    $cache->get('user_123');
    
    // Переключение на другую стратегию
    $cache->setStrategy(new FileCache());
    
  3. Для изоляции сложной бизнес-логики от контекста её использования
    Если алгоритмы содержат сложную логику, которая может изменяться независимо от основного кода, Стратегия помогает соблюсти принцип единственной ответственности (SRP). Например, расчёт налогов для разных стран или регионов: каждый расчёт — отдельная стратегия, а основной класс работы с заказом не зависит от деталей вычислений.

  4. Когда нужно упростить тестирование и повысить модульность
    Поскольку каждая стратегия инкапсулирована в собственном классе, её легко тестировать изолированно с помощью юнит-тестов. Кроме того, это способствует повторному использованию кода: стратегии можно комбинировать в других контекстах без дублирования логики.

    // Тест стратегии
    class DiscountStrategyTest extends \PHPUnit\Framework\TestCase {
        public function testPercentageDiscount() {
            $strategy = new PercentageDiscountStrategy(10); // 10% скидка
            $this->assertEquals(90, $strategy->apply(100));
        }
    }
    
  5. Для замены наследования композицией
    Вместо создания глубоких иерархий классов с переопределением методов (например, class PayPalPayment extends Payment), лучше использовать композицию — внедрение стратегий. Это соответствует принципу «предпочитайте композицию наследованию» и делает систему более гибкой.

Практические примеры из PHP-разработки

  • Системы оплаты: Выбор между PayPal, Stripe, банковскими картами и т.д.
  • Логирование: Запись логов в файл, отправка в Syslog, сохранение в базу данных или отправка в Elasticsearch.
  • Валидация данных: Различные стратегии валидации для разных типов входных данных (email, телефон, JSON-схема).
  • Генерация отчётов: Экспорт в PDF, CSV, Excel или HTML с общей структурой генерации.
  • Алгоритмы рекомендаций: Разные алгоритмы подбора контента (на основе истории просмотров, популярности, демографии).

Ограничения и предостережения

Не стоит применять Стратегию, если алгоритмов всего один или два и они unlikely to change — это может привести к избыточной сложности. Также важно помнить о производительности: создание множества объектов-стратегий в высоконагруженных циклах может быть накладным, в таких случаях可以考虑 кэширование или другие оптимизации.

Итог: Паттерн Стратегия в PHP — это мощный инструмент для управления изменяющимися алгоритмами, повышения гибкости кода и соблюдения принципов SOLID. Его стоит применять при явной необходимости варьировать поведение системы и изолировать сложную логику для упрощения поддержки и тестирования.

Когда применять паттерн проектирования Стратегия в PHP? | PrepBro