Strategy виносить взаємозамінні алгоритми в окремі класи за спільним інтерфейсом, щоб підставляти їх без зміни клієнта.
Яку проблему вирішує
Коли одну дію можна виконати різними способами (тарифи, доставка, знижки, фільтри), вибір через if/switch робить сервіс громіздким. Кожен новий варіант - правка цього сервісу й ризик зачепити сусідні гілки.
Як вирішує
Кожен алгоритм інкапсулюється в окремому класі зі спільним інтерфейсом. Сервіс працює з інтерфейсом і не знає деталей. У Laravel зручно обирати стратегію через контейнер або конфіг - тоді заміна логіки відбувається без правок сервісу.
interface PriceStrategy
{
public function calc($order);
}
class RetailPrice implements PriceStrategy
{
public function calc($order)
{
return $order->total;
}
}
class VipPrice implements PriceStrategy
{
public function calc($order)
{
return $order->total * 0.9;
}
}
class OrderService
{
public function __construct(private PriceStrategy $strategy) {}
public function total($order)
{
return $this->strategy->calc($order);
}
}
app()->bind(PriceStrategy::class, VipPrice::class);
Де застосовувати
- Тарифи, способи доставки, знижки, фільтри - будь-яка дія з кількома варіантами виконання.
- Коли набір алгоритмів розширюється й хочеться додавати їх без правок наявного коду.
Плюси та мінуси
- + Прибирає каскади
if/switch; кожен алгоритм тестується локально.
- + Система розширюється новими стратегіями без ризику зламати наявні.
- − Більше класів і потреба десь обирати потрібну стратегію.
- − Для двох простих варіантів окремі класи - надмірність; вистачить
match.