Wzorzec Strategy
Część sekcji Programowanie obiektowe ścieżki Python w Coddy. Lekcja 48 z 64.
Wzorzec Strategia definiuje rodzinę algorytmów, hermetyzuje każdy z nich i umożliwia ich wzajemną wymianę. Możesz przełączać algorytmy w czasie działania programu bez zmieniania kodu klienta.
Oto proste klasy strategii dla różnych metod płatności:
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"Każda strategia implementuje tę samą metodę (pay), ale zachowuje się inaczej.
Utwórz klasę kontekstu, która używa strategii:
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)Klasa kontekstu może przełączać się między różnymi strategiami płatności.
Użyj wzorca strategii:
cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)
# Użyj strategii płatności kartą kredytową
cart.set_payment_strategy(CreditCard())
print(cart.checkout())
# Przełącz na strategię płatności PayPal
cart.set_payment_strategy(PayPal())
print(cart.checkout())Utwórz kolejny przykład ze strategiami sortowania:
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)
# Użyj różnych strategii sortowania
numbers = [3, 1, 4, 1, 5]
sorter = Sorter(BubbleSort())
print(sorter.sort_data(numbers))
sorter.set_strategy(QuickSort())
print(sorter.sort_data(numbers))Wynik:
Paid $80 with Credit Card
Paid $80 with PayPal
Bubble sorted: [1, 1, 3, 4, 5]
Quick sorted: [1, 1, 3, 4, 5]Kluczowa kwestia: Wzorzec Strategia pozwala zmieniać algorytmy w czasie działania programu. Zdefiniuj różne strategie z tym samym interfejsem, a następnie pozwól klasie kontekstu wybrać, której użyć. Dzięki temu Twój kod jest elastyczny i łatwy do rozszerzania o nowe algorytmy bez zmieniania istniejącego kodu.
Wyzwanie
ŚredniZaimplementuj nową strategię BitcoinPayment dla naszego systemu zakupów.
Twoje zadanie:
- Utwórz klasę BitcoinPayment implementującą PaymentStrategy
- Powinna przyjmować wallet_address w konstruktorze
- Metoda pay powinna wypisać dokładnie:
Paying $X using Bitcoin wallet: Y, gdzie X to kwota, a Y to adres portfela - Po wypisaniu metoda pay powinna zwrócić True
- Napisz funkcję main, która:
- Tworzy koszyk zakupowy
- Dodaje do koszyka laptopa kosztującego $1200 i słuchawki kosztujące $100
- Tworzy BitcoinPayment z adresem portfela "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
- Ustawia tę strategię płatności w koszyku
- Wywołuje metodę checkout
Kod początkowy zawiera już na dole if __name__ == "__main__":. Nie musisz dodawać tego samodzielnie. To konwencja Pythona, która gwarantuje, że funkcja main() uruchomi się tylko wtedy, gdy plik zostanie wykonany bezpośrednio (a nie zaimportowany przez inny moduł). Wystarczy zdefiniować funkcję main(), a podany blok wywoła ją automatycznie.
Postępuj zgodnie z tą samą strukturą, co w przykładach z lekcji.
Spróbuj swoich sił
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")
# Utwórz tutaj klasę strategii BitcoinPayment
if __name__ == "__main__":
main()Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektyParametr selfMetodyAtrybutyMetoda konstruktora (__init__)Powtórzenie – prosty kalkulator4Dziedziczenie
Podstawy dziedziczeniaFunkcja super()Nadpisywanie metodDziedziczenie wielokrotneKolejność rozwiązywania metodPodsumowanie – hierarchia pracowników7Metody specjalne
Wprowadzenie do metod magicznychPrzeciążanie operatorówMagiczne metody kontenerówPowtórka – własna lista10Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy2Dekoratory
Wprowadzenie do dekoratorówDekorator propertyDekorator metody statycznejDekorator metody klasowej5Polimorfizm
Ponowne omówienie nadpisywania metodTypowanie kaczeKlasy i metody abstrakcyjneProjektowanie interfejsówPodsumowanie — kalkulator kształtów8Zaawansowane koncepcje programowania obiektowego
Kompozycja a dziedziczenieMiksyMetody statyczne i klasoweDekoratory klasMenedżery kontekstu11Wzorce projektowe, część 2
Wzorzec PolecenieWzorzec AdapterWzorzec DekoratorWzorzec Metoda szablonowaWzorzec StanWzorzec Kompozyt3Właściwości klas
Zmienne instancji a zmienne klasoweDekoratory właściwościAtrybuty prywatnePowtórzenie — menedżer kont bankowych6Hermetyzacja
Public, Protected, Private — pamięćModyfikatory dostępuUkrywanie informacjiDekoratory właściwości — zaawansowanePodsumowanie — system ewidencji uczniów12Projekt: System zarządzania biblioteką
Przegląd projektuKlasy Book i UserSystem wypożyczeńFunkcja wyszukiwaniaInterfejs administratoraTestowanie i integracjaPoćwicz samodzielnie: Kompilator Python online