Modello Strategy
Fa parte della sezione Programmazione orientata agli oggetti del percorso Python di Coddy. Lezione 48 di 64.
Lo Strategy Pattern definisce una famiglia di algoritmi, incapsula ciascuno di essi e li rende intercambiabili. Puoi cambiare algoritmo durante l'esecuzione senza modificare il codice client.
Ecco semplici classi strategia per diversi metodi di pagamento:
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"Ogni strategia implementa lo stesso metodo (pay), ma con un comportamento diverso.
Crea una classe contesto che utilizza strategie:
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)La classe contesto può passare da una strategia di pagamento all'altra.
Usa il pattern strategia:
cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)
# Usa la strategia di pagamento con carta di credito
cart.set_payment_strategy(CreditCard())
print(cart.checkout())
# Passa alla strategia di pagamento PayPal
cart.set_payment_strategy(PayPal())
print(cart.checkout())Crea un altro esempio con strategie di ordinamento:
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)
# Usa diverse strategie di ordinamento
numbers = [3, 1, 4, 1, 5]
sorter = Sorter(BubbleSort())
print(sorter.sort_data(numbers))
sorter.set_strategy(QuickSort())
print(sorter.sort_data(numbers))Output:
Paid $80 with Credit Card
Paid $80 with PayPal
Bubble sorted: [1, 1, 3, 4, 5]
Quick sorted: [1, 1, 3, 4, 5]Punto chiave: il pattern Strategy ti permette di sostituire gli algoritmi durante l'esecuzione. Definisci strategie diverse con la stessa interfaccia, poi lascia che la classe contesto scelga quale usare. Questo rende il tuo codice flessibile e facile da estendere con nuovi algoritmi senza modificare il codice esistente.
Sfida
MedioImplementa una nuova strategia BitcoinPayment per il nostro sistema di acquisti.
Il tuo compito è:
- Creare una classe BitcoinPayment che implementi PaymentStrategy
- Deve accettare un wallet_address nel costruttore
- Il metodo pay deve stampare esattamente:
Paying $X using Bitcoin wallet: Ydove X è l'importo e Y è l'indirizzo del portafoglio - Il metodo pay deve restituire True dopo la stampa
- Scrivere una funzione main che:
- Crea un carrello della spesa
- Aggiunge al carrello un laptop del costo di $1200 e delle cuffie del costo di $100
- Crea un BitcoinPayment con l'indirizzo del portafoglio "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
- Imposta questa strategia di pagamento sul carrello
- Chiama il metodo checkout
Il codice iniziale include già if __name__ == "__main__": in fondo. Non è necessario aggiungerlo. Questa è una convenzione di Python che garantisce che la funzione main() venga eseguita solo quando il file viene eseguito direttamente (non quando viene importato da un altro modulo). Definisci semplicemente la funzione main() e il blocco fornito la chiamerà automaticamente.
Segui la stessa struttura mostrata negli esempi della lezione.
Provalo tu
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")
# Crea qui la tua classe di strategia BitcoinPayment
if __name__ == "__main__":
main()Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP
File esterniIntroduzione a OOPClassi vs. oggettiIl parametro selfMetodiAttributiMetodo costruttore (__init__)Riepilogo - Calcolatrice semplice4Ereditarietà
Ereditarietà di baseLa funzione super()Sovrascrittura dei metodiEreditarietà multiplaOrdine di risoluzione dei metodiRiepilogo - Gerarchia dei dipendenti7Metodi speciali
Introduzione ai metodi magiciSovraccarico degli operatoriMetodi magici dei contenitoriRiepilogo - Lista personalizzata10Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello ObserverModello Strategy2Decoratori
Introduzione ai decoratoriDecoratore di proprietàDecoratore di metodo staticoDecoratore di metodo di classe5Polimorfismo
Ripasso dell'override dei metodiDuck typingClassi e metodi astrattiProgettazione delle interfacceRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàMixinMetodi statici e di classeDecorator di classeContext manager11Pattern di progettazione - Parte 2
Pattern dei comandiPattern adattatorePattern decoratorePattern metodo templatePattern statoPattern composito3Proprietà delle classi
Variabili di istanza e di classeDecorator delle proprietàAttributi privatiRiepilogo - Gestore di conti bancari6Incapsulamento
Membri pubblici, protetti e privatiModificatori di accessoOccultamento delle informazioniDecorator delle proprietà: avanzatiRipasso - Sistema di registri degli studenti12Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e UtenteSistema di prestitoFunzionalità di ricercaInterfaccia amministratoreTest e integrazioneEsercitati da solo: Compilatore Python online