Что такое паттерн Стратегия и в каких случаях его стоит применять

Ответ

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

Его применяют, когда:

  • Есть несколько вариантов одного алгоритма, и нужно переключаться между ними в рантайме.
  • Необходимо изолировать логику алгоритмов от клиентского кода, который их использует.
  • Нужно избежать множества условных операторов (if-elif-else) для выбора поведения.

Пример на Python: Система оплаты с разными способами (карта, PayPal).

from abc import ABC, abstractmethod

# 1. Интерфейс Стратегии
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: int):
        pass

# 2. Конкретные Стратегии
class CreditCardPayment(PaymentStrategy):
    def pay(self, amount: int):
        print(f"Оплачено {amount} руб. с помощью кредитной карты.")

class PayPalPayment(PaymentStrategy):
    def pay(self, amount: int):
        print(f"Оплачено {amount} руб. через PayPal.")

# 3. Контекст, который использует Стратегию
class PaymentContext:
    def __init__(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def set_strategy(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def execute_payment(self, amount: int):
        self._strategy.pay(amount)

# Использование
cart = PaymentContext(CreditCardPayment())
cart.execute_payment(1000)
# > Оплачено 1000 руб. с помощью кредитной карты.

# Динамическая смена стратегии
cart.set_strategy(PayPalPayment())
cart.execute_payment(500)
# > Оплачено 500 руб. через PayPal.

Преимущества:

  • Гибкость: Позволяет добавлять новые алгоритмы, не изменяя клиентский код.
  • Изоляция: Логика алгоритмов отделена от основной бизнес-логики.
  • Читаемость: Устраняет сложные условные конструкции.

Ответ 18+ 🔞

Так, слушай, смотри, есть у нас такая штука — паттерн Стратегия. Это, блядь, как если бы ты шёл нахуй, а у тебя в кармане не один, а три разных способа туда дойти: можно пешком, можно на велике, а можно, ёпта, на такси. И ты выбираешь на ходу, в зависимости от погоды, настроения и наличия бабла. Вот это и есть стратегия — семейство алгоритмов, которые можно менять прямо во время выполнения, не ломая весь код.

Зачем это надо? Ну, например, когда у тебя куча этих if-elif-else, которые раздуваются, как жопа после новогодних праздников, и ты уже сам не понимаешь, что там происходит. Или когда нужно изолировать логику, чтобы не получилось пиздеца, если завтра придётся добавить ещё один способ оплаты, кроме карты и PayPal.

Смотри, как это выглядит на Python — на примере оплаты, чтобы было понятно даже тому, у кого с программированием, как у меня с балетом.

from abc import ABC, abstractmethod

# 1. Интерфейс Стратегии
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: int):
        pass

# 2. Конкретные Стратегии
class CreditCardPayment(PaymentStrategy):
    def pay(self, amount: int):
        print(f"Оплачено {amount} руб. с помощью кредитной карты.")

class PayPalPayment(PaymentStrategy):
    def pay(self, amount: int):
        print(f"Оплачено {amount} руб. через PayPal.")

# 3. Контекст, который использует Стратегию
class PaymentContext:
    def __init__(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def set_strategy(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def execute_payment(self, amount: int):
        self._strategy.pay(amount)

# Использование
cart = PaymentContext(CreditCardPayment())
cart.execute_payment(1000)
# > Оплачено 1000 руб. с помощью кредитной карты.

# Динамическая смена стратегии
cart.set_strategy(PayPalPayment())
cart.execute_payment(500)
# > Оплачено 500 руб. через PayPal.

Видишь? Мы создали интерфейс PaymentStrategy — это как договор: «Любой способ оплаты должен уметь делать pay». Потом наделали конкретных реализаций — карта, PayPal, хоть криптой можно добавить, если не боишься остаться без штанов. А PaymentContext — это наш главный по оплатам, он не парится, как именно платить, он просто тыкает в выбранную стратегию и говорит: «Работай!».

Что хорошего?
Гибкость: Хочешь добавить оплату через «СберПэй»? Просто создаёшь новый класс, реализуешь метод pay и подсовываешь контексту. Ничего не ломается, все довольны.
Изоляция: Логика оплаты сидит в своих классах, не лезет в основной код, не устраивает там пиздец.
Читаемость: Никаких километровых if-ов, всё чисто, понятно, как белый свет после трёх дней запоя.

В общем, стратегия — это овердохуища полезная штука, когда нужно менять поведение на лету, не переписывая пол-проекта. Запомни это, а то будешь потом, как Герасим, только «Му-му» говорить, когда код начнёт разваливаться.