Паттерн «Стратегия»
Часть раздела Объектно-ориентированное программирование путешествия по Python на Coddy. Урок 48 из 64.
Паттерн «Стратегия» определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Вы можете переключать алгоритмы во время выполнения программы, не изменяя клиентский код.
Вот простые классы стратегий для разных способов оплаты:
class CreditCard:
def pay(self, amount):
return f"Paid ${amount} with Credit Card"
class PayPal:
def pay(self, amount):
return f"Paid ${amount} with PayPal"
class Bitcoin:
def pay(self, amount):
return f"Paid ${amount} with Bitcoin"Каждая стратегия реализует один и тот же метод (pay), но с разным поведением.
Создай класс контекста, который использует стратегии:
class ShoppingCart:
def __init__(self):
self.total = 0
self.payment_strategy = None
def add_item(self, price):
self.total += price
def set_payment_strategy(self, strategy):
self.payment_strategy = strategy
def checkout(self):
return self.payment_strategy.pay(self.total)Класс контекста может переключаться между различными стратегиями оплаты.
Используй шаблон стратегии:
cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)
# Используйте стратегию оплаты кредитной картой
cart.set_payment_strategy(CreditCard())
print(cart.checkout())
# Переключитесь на стратегию оплаты через PayPal
cart.set_payment_strategy(PayPal())
print(cart.checkout())Создай ещё один пример с алгоритмами сортировки:
class BubbleSort:
def sort(self, data):
return f"Bubble sorted: {sorted(data)}"
class QuickSort:
def sort(self, data):
return f"Quick sorted: {sorted(data)}"
class Sorter:
def __init__(self, strategy):
self.strategy = strategy
def set_strategy(self, strategy):
self.strategy = strategy
def sort_data(self, data):
return self.strategy.sort(data)
# Используйте разные стратегии сортировки
numbers = [3, 1, 4, 1, 5]
sorter = Sorter(BubbleSort())
print(sorter.sort_data(numbers))
sorter.set_strategy(QuickSort())
print(sorter.sort_data(numbers))Вывод:
Paid $80 with Credit Card
Paid $80 with PayPal
Bubble sorted: [1, 1, 3, 4, 5]
Quick sorted: [1, 1, 3, 4, 5]Ключевой момент: паттерн «Стратегия» позволяет менять алгоритмы во время выполнения. Определите разные стратегии с одним и тем же интерфейсом, а затем позвольте классу контекста выбрать, какую из них использовать. Это делает ваш код гибким и позволяет легко расширять его новыми алгоритмами, не изменяя существующий код.
Задание
СреднеРеализуйте новую стратегию BitcoinPayment для нашей системы покупок.
Ваша задача:
- Создать класс BitcoinPayment, реализующий PaymentStrategy
- Он должен принимать wallet_address в конструкторе
- Метод pay должен вывести в точности:
Paying $X using Bitcoin wallet: Y, где X — сумма, а Y — адрес кошелька - После вывода метод pay должен вернуть True
- Написать функцию main, которая:
- Создаёт корзину покупок
- Добавляет в корзину ноутбук стоимостью $1200 и наушники стоимостью $100
- Создаёт BitcoinPayment с адресом кошелька "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
- Устанавливает эту стратегию оплаты для корзины
- Вызывает метод checkout
Стартовый код уже содержит if __name__ == "__main__": внизу. Добавлять его самостоятельно не нужно. Это соглашение Python гарантирует, что функция main() запускается, только когда файл выполняется напрямую (а не импортируется другим модулем). Просто определите функцию main(), и предоставленный блок вызовет её автоматически.
Следуйте той же структуре, что и в примерах урока.
Попробуйте сами
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
class CreditCardPayment(PaymentStrategy):
def __init__(self, card_number, expiry_date, cvv):
self.card_number = card_number
self.expiry_date = expiry_date
self.cvv = cvv
def pay(self, amount):
print(f"Paying ${amount} using Credit Card: {self.card_number}")
return True
class PayPalPayment(PaymentStrategy):
def __init__(self, email, password):
self.email = email
self.password = password
def pay(self, amount):
print(f"Paying ${amount} using PayPal account: {self.email}")
return True
class ShoppingCart:
def __init__(self):
self.items = []
self.payment_strategy = None
def add_item(self, item, price):
self.items.append({"item": item, "price": price})
def set_payment_strategy(self, payment_strategy):
self.payment_strategy = payment_strategy
def checkout(self):
total = sum(item["price"] for item in self.items)
if self.payment_strategy:
return self.payment_strategy.pay(total)
else:
raise ValueError("No payment strategy set")
# Создайте здесь класс стратегии BitcoinPayment
if __name__ == "__main__":
main()В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Введение в ООПВнешние файлыКлассы и объектыПараметр selfМетодыАтрибутыМетод-конструктор (__init__)Повторение — простой калькулятор4Наследование
Основы наследованияФункция super()Переопределение методовМножественное наследованиеПорядок разрешения методовПовторение: иерархия сотрудников7Специальные методы
Введение в магические методыПерегрузка операторовМагические методы контейнеровПовторение — пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн «Одиночка»Паттерн «Фабрика»Паттерн «Наблюдатель»Паттерн «Стратегия»2Декораторы
Введение в декораторыДекоратор свойстваДекоратор статического методаДекоратор метода класса5Полиморфизм
Переопределение методов: повторениеУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовПовторение — калькулятор фигур8Продвинутые концепции ООП
Композиция и наследованиеМиксиныСтатические методы и методы классаДекораторы классовМенеджеры контекста11Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»3Свойства классов
Переменные экземпляра и классаДекораторы свойствПриватные атрибутыПовторение — менеджер банковского счёта6Инкапсуляция
Публичные, защищённые и приватные членыМодификаторы доступаСокрытие информацииПродвинутые декораторы свойствПовторение — система учёта студентов12Проект: Система управления библиотекой
Обзор проектаКлассы книг и пользователейСистема выдачи книгФункция поискаИнтерфейс администратораТестирование и интеграцияПотренируйтесь самостоятельно: Онлайн-компилятор Python