Patron Stratégie
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy. Leçon 55 sur 70.
Le pattern Strategy est un pattern comportemental qui vous permet de définir une famille d’algorithmes, d’encapsuler chacun d’eux dans sa propre classe et de les rendre interchangeables lors de l’exécution. Au lieu de coder le comportement en dur, vous injectez la stratégie souhaitée dans un objet.
Le modèle se compose de trois parties : une interface de stratégie qui définit le contrat de l’algorithme, des classes de stratégie concrètes qui implémentent différents comportements, et une classe de contexte qui utilise une stratégie :
public interface IPaymentStrategy
{
void Pay(decimal amount);
}
public class CreditCardPayment : IPaymentStrategy
{
public void Pay(decimal amount) =>
Console.WriteLine($"Paid {amount} via Credit Card");
}
public class PayPalPayment : IPaymentStrategy
{
public void Pay(decimal amount) =>
Console.WriteLine($"Paid {amount} via PayPal");
}
public class ShoppingCart
{
private IPaymentStrategy _paymentStrategy;
public void SetPaymentMethod(IPaymentStrategy strategy)
{
_paymentStrategy = strategy;
}
public void Checkout(decimal total)
{
_paymentStrategy.Pay(total);
}
}Le contexte (ShoppingCart) ne sait pas quelle méthode de paiement il utilise : il appelle simplement Pay() sur la stratégie fournie :
var cart = new ShoppingCart();
cart.SetPaymentMethod(new CreditCardPayment());
cart.Checkout(99.99m); // Payé 99.99 via Credit Card
cart.SetPaymentMethod(new PayPalPayment());
cart.Checkout(49.99m); // Payé 49.99 via PayPalLe modèle Strategy élimine la logique conditionnelle complexe. Ajouter un nouveau mode de paiement signifie créer une nouvelle classe qui implémente IPaymentStrategy - aucune modification n’est nécessaire dans ShoppingCart. Cela rend votre code ouvert à l’extension, mais fermé à la modification.
Défi
FacileConstruisons un calculateur de frais d’expédition utilisant le pattern Strategy. Les différentes méthodes d’expédition ont des algorithmes de tarification différents, et votre système doit permettre de passer de l’une à l’autre lors de l’exécution sans modifier la logique centrale de traitement des commandes.
Vous organiserez votre code sur trois fichiers :
ShippingStrategy.cs: définissez une interfaceIShippingStrategydans l’espace de nomsShippingavec une méthodeCalculateCost(double weight)qui renvoie undouble. Créez ensuite trois classes de stratégie concrètes :StandardShipping- calcule le coût commeweight * 1.5ExpressShipping- calcule le coût commeweight * 3.0 + 5.0(inclut des frais fixes pour l’expédition express)OvernightShipping- calcule le coût commeweight * 5.0 + 10.0(service premium avec des frais de base plus élevés)
OrderProcessor.cs: créez une classeOrderProcessordans le même espace de noms. Il s’agit de votre classe de contexte, qui utilise une stratégie d’expédition. Elle doit comporter :- un champ privé contenant la valeur actuelle de
IShippingStrategy - une méthode
SetShippingMethod(IShippingStrategy strategy)permettant de modifier la stratégie d’expédition - une méthode
ProcessOrder(double weight)qui utilise la stratégie actuelle pour calculer et renvoyer les frais d’expédition
- un champ privé contenant la valeur actuelle de
Program.cs: assemblez tous les éléments en créant unOrderProcessoret en montrant comment échanger les stratégies d’expédition lors de l’exécution. Le même processeur peut calculer les coûts à l’aide de différents algorithmes, simplement en modifiant sa stratégie.
Vous recevrez deux entrées :
- le type de méthode d’expédition :
standard,expressouovernight - le poids du colis sous forme de nombre décimal (par exemple,
4.5)
Créez un OrderProcessor, définissez la stratégie d’expédition appropriée en fonction du type fourni, puis traitez la commande et affichez le coût calculé.
Par exemple, si les entrées sont express et 4.5, la sortie doit être :
18.5Cela démontre toute la puissance du pattern Strategy : votre OrderProcessor ne contient lui-même aucune logique de calcul des frais d’expédition. Il délègue simplement la tâche à la stratégie qui lui a été attribuée, ce qui facilite l’ajout de nouvelles méthodes d’expédition (comme DroneDelivery) sans modifier le processeur !
Essayez vous-même
using System;
using Shipping;
class Program
{
public static void Main(string[] args)
{
// Lire l'entrée
string shippingType = Console.ReadLine();
double weight = Convert.ToDouble(Console.ReadLine());
// TODO: Créer une instance d'OrderProcessor
// TODO: En fonction de shippingType ("standard", "express", or "overnight"),
// créer la stratégie d'expédition appropriée et l'assigner au processeur
// TODO: Traiter la commande et afficher le coût calculé
}
}
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
1Fondamentaux de la POO
Fichiers externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et UtilisateurLogique du système d'empruntLINQ pour la rechercheInterface Console / Interface d'administrationTests unitaires (NUnit/xUnit)Entraînez-vous par vous-même : Compilateur C# en ligne