Что это такое
Паттерн Стратегия (Strategy) делает алгоритм заменяемым: окружающий код остаётся прежним, а взаимозаменяемая часть — как считать цену, как сортировать, как сжимать — подключается как значение.
Этот паттерн Python упрощает сильнее всего: поскольку функции — полноценные значения, стратегия часто представляет собой обычную функцию. Ни протокола, ни класса — присвойте другую функцию, и поведение изменится.
Пример: заменяемое ценообразование
checkout() никогда не меняется; правило расчёта цены — это функция, хранящаяся в поле. Обычная цена, «Чёрная пятница», скидка для участника — три функции, один магазин.
Стратегия — это функция
Три оформления заказа на одну и ту же сумму 50 дают три разных итога — различается только присвоенная функция. Так же работает и sorted(): функция key, которую вы ей передаёте, и есть стратегия сравнения.
Вывод: полная программа на Python
from typing import Callable
# В Python стратегия — это просто функция.
Pricing = Callable[[float], float]
def regular(price: float) -> float:
return price
def black_friday(price: float) -> float:
return price * 0.7
def member(price: float) -> float:
return price - 5
class Shop:
def __init__(self, pricing: Pricing) -> None:
self.pricing = pricing
def checkout(self, price: float) -> None:
print(f"итого: {self.pricing(price):.2f}")
shop = Shop(regular)
shop.checkout(50)
shop.pricing = black_friday
shop.checkout(50)
shop.pricing = member
shop.checkout(50)
Когда использовать
Используйте его, когда алгоритм меняется, а его окружение — нет: правила ценообразования, политики повторных попыток, порядки сортировки, режимы проверки.
Не используйте его, когда алгоритм один и реального второго не предвидится. Используйте класс вместо функции, только если стратегии нужно собственное состояние или несколько методов.
Плюсы и минусы
Плюсы: поведение меняется во время выполнения; каждая стратегия небольшая и тестируется отдельно; в Python это почти ничего не стоит — обычная функция и присваивание.
Минусы: выбранная стратегия не видна в месте вызова — при отладке нужно выяснять, что было присвоено; слишком много мелких стратегий дробят простую логику.