Strategy-Muster
Teil des Abschnitts Object Oriented Programming der Python-Journey von Coddy — Lektion 48 von 64.
Das Strategy-Pattern definiert eine Familie von Algorithmen, kapselt jeden einzelnen und macht sie austauschbar. Sie können Algorithmen zur Laufzeit austauschen, ohne den Client-Code zu ändern.
Hier sind einfache Strategie-Klassen für verschiedene Zahlungsmethoden:
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"Jede Strategie implementiert dieselbe Methode (pay), aber mit unterschiedlichem Verhalten.
Erstellen Sie eine Kontext-Klasse, die Strategien verwendet:
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)Die Context-Klasse kann zwischen verschiedenen Zahlungsstrategien wechseln.
Verwenden Sie das Strategiemuster:
cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)
# Kreditkarten-Strategie verwenden
cart.set_payment_strategy(CreditCard())
print(cart.checkout())
# Zu PayPal-Strategie wechseln
cart.set_payment_strategy(PayPal())
print(cart.checkout())Erstellen Sie ein weiteres Beispiel mit Sortierstrategien:
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)
# Verwenden Sie verschiedene Sortierstrategien
numbers = [3, 1, 4, 1, 5]
sorter = Sorter(BubbleSort())
print(sorter.sort_data(numbers))
sorter.set_strategy(QuickSort())
print(sorter.sort_data(numbers))Ausgabe:
Paid $80 with Credit Card
Paid $80 with PayPal
Bubble sorted: [1, 1, 3, 4, 5]
Quick sorted: [1, 1, 3, 4, 5]Kernpunkt: Das Strategy-Pattern ermöglicht es Ihnen, Algorithmen zur Laufzeit auszutauschen. Definieren Sie verschiedene Strategien mit derselben Schnittstelle und lassen Sie dann die Kontextklasse entscheiden, welche verwendet werden soll. Dies macht Ihren Code flexibel und einfach um neue Algorithmen erweiterbar, ohne bestehenden Code ändern zu müssen.
Aufgabe
MittelImplementieren Sie eine neue BitcoinPayment-Strategie für unser Einkaufssystem.
Ihre Aufgabe ist es:
- Erstellen Sie eine BitcoinPayment-Klasse, die PaymentStrategy implementiert
- Sie sollte eine wallet_address im Konstruktor akzeptieren
- Die pay-Methode sollte genau Folgendes ausgeben:
Paying $X using Bitcoin wallet: Y, wobei X der Betrag und Y die Wallet-Adresse ist - Die pay-Methode sollte nach der Ausgabe True zurückgeben
- Schreiben Sie eine main-Funktion, die:
- Einen Einkaufswagen (ShoppingCart) erstellt
- Einen Laptop für $1200 und Kopfhörer für $100 zum Einkaufswagen hinzufügt
- Ein BitcoinPayment mit der Wallet-Adresse "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa" erstellt
- Diese Zahlungsstrategie für den Einkaufswagen festlegt
- Die checkout-Methode aufruft
Der Starter-Code enthält bereits if __name__ == "__main__": am Ende — Sie müssen dies nicht selbst hinzufügen. Dies ist eine Python-Konvention, die sicherstellt, dass Ihre main()-Funktion nur ausgeführt wird, wenn die Datei direkt ausgeführt wird (nicht, wenn sie von einem anderen Modul importiert wird). Definieren Sie einfach Ihre main()-Funktion, und der bereitgestellte Block wird sie automatisch aufrufen.
Folgen Sie derselben Struktur, wie sie in den Lektionsbeispielen gezeigt wurde.
Spickzettel
Das Strategy-Pattern definiert eine Familie von Algorithmen, kapselt jeden einzelnen und macht sie austauschbar. Sie können Algorithmen zur Laufzeit wechseln, ohne den Client-Code zu ändern.
Erstellen Sie Strategie-Klassen mit derselben Schnittstelle:
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"Erstellen Sie eine Kontext-Klasse, die Strategien verwendet:
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)Verwenden Sie das Strategiemuster:
cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)
# Kreditkarten-Strategie verwenden
cart.set_payment_strategy(CreditCard())
print(cart.checkout())
# Zu PayPal-Strategie wechseln
cart.set_payment_strategy(PayPal())
print(cart.checkout())Ein weiteres Beispiel mit Sortierstrategien:
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)Probier es selbst
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")
# Erstellen Sie hier Ihre BitcoinPayment-Strategieklasse
if __name__ == "__main__":
main()Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Object Oriented Programming
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDer self-ParameterMethodenAttributeKonstruktor-Methode (__init__)Zusammenfassung – Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDie super()-FunktionMethoden überschreibenMehrfachvererbungMethod Resolution OrderZusammenfassung - Mitarbeiter-Hierarchie7Spezielle Methoden
Einführung in Magic MethodsOperator-ÜberladungMagic Methods für ContainerRückblick - Eigene Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster13Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung2Dekoratoren
Einführung in DekoratorenProperty-DekoratorStatischer Methoden-DekoratorKlassenmethoden-Dekorator5Polymorphismus
Methoden-Überschreiben vertieftDuck TypingAbstrakte Klassen und MethodenInterface-DesignZusammenfassung – Formen-Rechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungMixinsStatische und KlassenmethodenKlassendekoratorenContext Manager3Klasseneigenschaften
Instanz- vs. KlassenvariablenProperty-DekoratorenPrivate AttributeZusammenfassung – Bankkonto-Manager6Kapselung
Public, Protected, Private MemberZugriffsmodifikatorenInformation HidingProperty-Decorators für FortgeschritteneZusammenfassung - Studentenverwaltungssystem12Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen