Menu
Coddy logo textTech

Patron Strategy

Fait partie de la section Object Oriented Programming du Journey Python de Coddy — leçon 48 sur 64.

Le patron de conception Stratégie définit une famille d'algorithmes, encapsule chacun d'eux et les rend interchangeables. Vous pouvez changer d'algorithme au moment de l'exécution sans modifier le code client.

Voici des classes de stratégie simples pour différents modes de paiement :

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"

Chaque stratégie implémente la même méthode (pay) mais avec un comportement différent.

Créez une classe de contexte qui utilise des stratégies :

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 contexte peut basculer entre différentes stratégies de paiement.

Utilisez le patron de conception stratégie :

cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)

# Utiliser la stratégie carte de crédit
cart.set_payment_strategy(CreditCard())
print(cart.checkout())

# Passer à la stratégie PayPal
cart.set_payment_strategy(PayPal())
print(cart.checkout())

Créez un autre exemple avec des stratégies de tri :

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)

# Utiliser différentes stratégies de tri
numbers = [3, 1, 4, 1, 5]

sorter = Sorter(BubbleSort())
print(sorter.sort_data(numbers))

sorter.set_strategy(QuickSort())
print(sorter.sort_data(numbers))

Résultat :

Paid $80 with Credit Card
Paid $80 with PayPal
Bubble sorted: [1, 1, 3, 4, 5]
Quick sorted: [1, 1, 3, 4, 5]

Point clé : Le patron de conception Stratégie (Strategy Pattern) vous permet d'échanger des algorithmes au moment de l'exécution. Définissez différentes stratégies avec la même interface, puis laissez la classe de contexte choisir laquelle utiliser. Cela rend votre code flexible et facile à étendre avec de nouveaux algorithmes sans modifier le code existant.

challenge icon

Défi

Moyen

Implémentez une nouvelle stratégie BitcoinPayment pour notre système d'achat.

Votre tâche consiste à :

  1. Créer une classe BitcoinPayment qui implémente PaymentStrategy
    • Elle doit accepter une wallet_address dans le constructeur
    • La méthode pay doit imprimer exactement : Paying $X using Bitcoin wallet: Y où X est le montant et Y est l'adresse du portefeuille
    • La méthode pay doit retourner True après l'impression
  2. Écrire une fonction main qui :
    • Crée un panier d'achat
    • Ajoute un ordinateur portable coûtant $1200 et des écouteurs coûtant $100 au panier
    • Crée un BitcoinPayment avec l'adresse de portefeuille "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
    • Définit cette stratégie de paiement sur le panier
    • Appelle la méthode checkout

Le code de départ inclut déjà if __name__ == "__main__": en bas — vous n'avez pas besoin de l'ajouter vous-même. C'est une convention Python qui garantit que votre fonction main() ne s'exécute que lorsque le fichier est exécuté directement (et non lorsqu'il est importé par un autre module). Définissez simplement votre fonction main() et le bloc fourni l'appellera automatiquement.

Suivez la même structure que celle présentée dans les exemples de la leçon.

Aide-mémoire

Le patron de conception Stratégie définit une famille d'algorithmes, encapsule chacun d'eux et les rend interchangeables. Vous pouvez changer d'algorithme au moment de l'exécution sans modifier le code client.

Créez des classes de stratégie avec la même interface :

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"

Créez une classe de contexte qui utilise les stratégies :

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)

Utilisez le patron de conception stratégie :

cart = ShoppingCart()
cart.add_item(50)
cart.add_item(30)

# Utiliser la stratégie de carte de crédit
cart.set_payment_strategy(CreditCard())
print(cart.checkout())

# Passer à la stratégie PayPal
cart.set_payment_strategy(PayPal())
print(cart.checkout())

Un autre exemple avec des stratégies de tri :

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)

Essayez vous-même

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")

# Créez votre classe de stratégie BitcoinPayment ici


if __name__ == "__main__":
    main()
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Object Oriented Programming