Patron Strategy
Fait partie de la section Programmation orientée objet du Journey Python de Coddy. Leçon 48 sur 64.
Le patron Strategy définit une famille d’algorithmes, encapsule chacun d’eux et les rend interchangeables. Vous pouvez changer d’algorithme lors de l’exécution sans modifier le code client.
Voici des classes de stratégie simples pour différentes méthodes 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 de contexte peut basculer entre différentes stratégies de paiement.
Utilisez le patron de 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())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))Sortie :
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 modèle Stratégie vous permet de remplacer les algorithmes lors de l’exécution. Définissez différentes stratégies avec la même interface, puis laissez la classe de contexte choisir laquelle utiliser. Votre code devient ainsi flexible et facile à étendre avec de nouveaux algorithmes, sans modifier le code existant.
Défi
MoyenImplémentez une nouvelle stratégie BitcoinPayment pour notre système d’achat.
Votre tâche consiste à :
- Créer une classe BitcoinPayment qui implémente PaymentStrategy
- Elle doit accepter un wallet_address dans le constructeur
- La méthode pay doit afficher 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’affichage
- Écrire une fonction main qui :
- Crée un panier d’achat
- Ajoute au panier un ordinateur portable coûtant $1200 et un casque coûtant $100
- 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 du fichier. Vous n’avez pas besoin de l’ajouter vous-même. Il s’agit d’une convention Python qui garantit que votre fonction main() s’exécute uniquement 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.
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")
# Create your BitcoinPayment strategy class here
if __name__ == "__main__":
main()Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Les fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe paramètre selfMéthodesAttributsMéthode constructeur (__init__)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLa fonction super()Redéfinition de méthodeHéritage multipleOrdre de résolution des méthodesRécapitulatif - Hiérarchie des employés7Méthodes spéciales
Introduction aux méthodes magiquesSurcharge d'opérateursMéthodes magiques de conteneurRécapitulatif - Liste personnalisée10Patrons de conception, Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy2Décorateurs
Introduction aux décorateursDécorateur de propriétéDécorateur de méthode statiqueDécorateur de méthode de classe5Polymorphisme
Retour sur la redéfinition de méthodeDuck TypingClasses et méthodes abstraitesConception d'interfacesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageMixinsMéthodes statiques et de classeDécorateurs de classeGestionnaires de contexte11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Propriétés de classe
Variables d'instance vs variables de classeDécorateurs de propriétéAttributs privésRécapitulatif - Gestionnaire de compte bancaireEntraînez-vous par vous-même : Compilateur Python en ligne