Menu
Coddy logo textTech

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.

challenge icon

Sfida

Medio

Implementa una nuova strategia BitcoinPayment per il nostro sistema di acquisti.

Il tuo compito è:

  1. 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: Y dove X è l'importo e Y è l'indirizzo del portafoglio
    • Il metodo pay deve restituire True dopo la stampa
  2. 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()
quiz iconMettiti alla prova

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

Esercitati da solo: Compilatore Python online