Стратегия — это поведенческий паттерн проектирования, который определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.
Пример на PHP
/** * Контекст определяет интерфейс, представляющий интерес для клиентов. */ class Context { /** * @var Strategy Контекст хранит ссылку на один из объектов Стратегии. * Контекст не знает конкретного класса стратегии. Он должен работать со * всеми стратегиями через интерфейс Стратегии. */ private $strategy; /** * Обычно Контекст принимает стратегию через конструктор, а также * предоставляет сеттер для её изменения во время выполнения. */ public function __construct(Strategy $strategy) { $this->strategy = $strategy; } /** * Обычно Контекст позволяет заменить объект Стратегии во время выполнения. */ public function setStrategy(Strategy $strategy) { $this->strategy = $strategy; } /** * Вместо того, чтобы самостоятельно реализовывать множественные версии * алгоритма, Контекст делегирует некоторую работу объекту Стратегии. */ public function doSomeBusinessLogic(): void { // ... echo "Context: Sorting data using the strategy (not sure how it'll do it)\n"; $result = $this->strategy->doAlgorithm(["a", "b", "c", "d", "e"]); echo implode(",", $result) . "\n"; // ... } } /** * Интерфейс Стратегии объявляет операции, общие для всех поддерживаемых версий * некоторого алгоритма. * * Контекст использует этот интерфейс для вызова алгоритма, определённого * Конкретными Стратегиями. */ interface Strategy { public function doAlgorithm(array $data): array; } /** * Конкретные Стратегии реализуют алгоритм, следуя базовому интерфейсу * Стратегии. Этот интерфейс делает их взаимозаменяемыми в Контексте. */ class ConcreteStrategyA implements Strategy { public function doAlgorithm(array $data): array { sort($data); return $data; } } class ConcreteStrategyB implements Strategy { public function doAlgorithm(array $data): array { rsort($data); return $data; } } /** * Клиентский код выбирает конкретную стратегию и передаёт её в контекст. Клиент * должен знать о различиях между стратегиями, чтобы сделать правильный выбор. */ $context = new Context(new ConcreteStrategyA); echo "Client: Strategy is set to normal sorting.\n"; $context->doSomeBusinessLogic(); echo "\n"; echo "Client: Strategy is set to reverse sorting.\n"; $context->setStrategy(new ConcreteStrategyB); $context->doSomeBusinessLogic();
Пример на Laravel
Для начала создадим интерфейс:namespace App\Helpers\PaymentProcessors; //Handle any payment related Issues interface payStrategy{ /*Algorithms for the pattern*/ public function customerInquiry($request); public function pay($request); public function tranInquiry($request); }
Класс, имплементирующий интерфейс является классом стратегии:
namespace App\Helpers\PaymentProcessors; class PayByCard implements PayStrategy { public function __construct(){ } public function customerInquiry($request){ return “PayByCard: Customer details Here”; } public function pay($request){ return “PaybyCard: Payment Details here”; } public function tranInquiry($request){ return “PaybyCard: Transaction details”; } }
Если есть необходимость, можем создать другие имплементы:
namespace App\Helpers\PaymentProcessors; class PayByWallet implements PayStrategy { public function customerInquiry($request){ return “PayByWallet: Customer details Here”; } public function pay($request){ return “PayByWallet: Payment Details here”; } public function tranInquiry($request){ return “PayByWallet: Transaction details”; } }
Подключим классы стратегии (например, в контроллерах):
use App\Helpers\PaymentProcessors\PayByCard; use App\Helpers\PaymentProcessors\PayByWallet;
Использование стратегии:
public function __construct(){ /*some of the objects that shall be used*/ $this->transaction = new Transaction(); $this->payByWallet = new PayByWallet(); $this->payByCard = new PayByCard(); }