Patron Stratégie
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 69 sur 87.
Le Strategy Pattern est un patron de conception comportemental qui permet de définir une famille d'algorithmes, d'encapsuler chacun d'eux dans sa propre classe et de les rendre interchangeables. Au lieu de coder en dur un comportement spécifique, vous pouvez échanger les algorithmes au moment de l'exécution sans modifier le code qui les utilise.
Imaginez un système de paiement qui prend en charge plusieurs méthodes de paiement. Sans le modèle de stratégie (Strategy Pattern), vous vous retrouveriez avec une logique conditionnelle désordonnée. Avec lui, chaque méthode de paiement devient sa propre stratégie :
interface PaymentStrategy {
void pay(int amount);
}
class CreditCardPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Paid " + amount + " via Credit Card");
}
}
class PayPalPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Paid " + amount + " via PayPal");
}
}La classe context détient une référence vers une stratégie et lui délègue le travail. L'élément clé est que le contexte ne sait pas quelle stratégie concrète il utilise — il connaît seulement l'interface :
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}Maintenant, vous pouvez modifier le comportement de paiement de manière dynamique :
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(100); // Payé 100 via carte de crédit
cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(50); // Payé 50 via PayPalLe Strategy Pattern brille lorsque vous avez plusieurs façons d'effectuer une action et que vous souhaitez passer de l'une à l'autre facilement. Ajouter une nouvelle méthode de paiement signifie simplement créer une nouvelle classe qui implémente PaymentStrategy—aucune modification du code existant n'est requise.
Défi
FacileConstruisons un système de formatage de texte en utilisant le Strategy Pattern ! Vous allez créer un système où différentes stratégies de formatage peuvent être interchangées au moment de l'exécution pour transformer le texte de diverses manières — idéal pour une application qui doit prendre en charge plusieurs formats de sortie.
Vous organiserez votre code sur quatre fichiers :
TextFormatter.java: Définissez l'interfaceTextFormatterque toutes les stratégies de formatage implémenteront. Elle doit déclarer une seule méthodeString format(String text)qui prend une chaîne de caractères et renvoie la version formatée.Formatters.java: Créez trois stratégies concrètes qui implémentent votre interfaceTextFormatter:UpperCaseFormatter- transforme le texte en lettres majuscules.LowerCaseFormatter- transforme le texte en lettres minuscules.TitleCaseFormatter- met en majuscule la première lettre de chaque mot tout en mettant le reste en minuscules. Les mots sont séparés par des espaces.TextEditor.java: Créez la classe de contexte qui utilise une stratégie de formatage. VotreTextEditordoit avoir :Un champ privé pour stocker la stratégie
TextFormatteractuelle.Une méthode
setFormatter(TextFormatter formatter)qui change la stratégie de formatage active.Une méthode
publishText(String text)qui applique le formateur actuel au texte et affichePublished: [formatted text]. Si aucun formateur n'a été défini, elle doit afficherPublished: [original text]sans modification.Main.java: Rassemblez votre système de stratégie ! Vous recevrez deux entrées : le texte à formater (String) et le style de formatage (String :"upper","lower", ou"title").Créez un
TextEditoret appelez d'abordpublishTextavec votre texte d'entrée avant de définir un formateur (démontrant le comportement par défaut).Ensuite, en fonction de l'entrée de style, définissez la stratégie de formateur appropriée et appelez à nouveau
publishTextavec le même texte pour afficher le résultat formaté.
Vous recevrez deux entrées dans l'ordre : le texte à formater (String) et le style de formatage (String).
Par exemple, avec les entrées hello world et title, votre sortie serait :
Published: hello world
Published: Hello WorldRemarquez comment le TextEditor ne connaît rien de la logique de formatage spécifique — il délègue simplement à la stratégie actuellement définie. Cela rend trivial l'ajout de nouveaux styles de formatage sans toucher au code de l'éditeur !
Aide-mémoire
Le Strategy Pattern (ou patron de stratégie) est un patron de conception comportemental qui définit une famille d'algorithmes, encapsule chacun d'eux dans sa propre classe et les rend interchangeables. Il permet de changer d'algorithme au moment de l'exécution sans modifier le code qui les utilise.
Composants clés
Interface de stratégie : Définit l'interface commune pour toutes les stratégies concrètes.
interface PaymentStrategy {
void pay(int amount);
}Stratégies concrètes : Implémentent l'interface de stratégie avec des algorithmes spécifiques.
class CreditCardPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Paid " + amount + " via Credit Card");
}
}
class PayPalPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Paid " + amount + " via PayPal");
}
}Classe de contexte : Détient une référence à une stratégie et lui délègue le travail. Le contexte ne connaît que l'interface, pas l'implémentation concrète.
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}Utilisation
Les stratégies peuvent être modifiées dynamiquement au moment de l'exécution :
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(100); // Payé 100 via Credit Card
cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(50); // Payé 50 via PayPalAvantages
Le Strategy Pattern est idéal lorsque vous avez plusieurs façons d'effectuer une action et que vous souhaitez passer de l'une à l'autre facilement. Ajouter une nouvelle stratégie signifie simplement créer une nouvelle classe qui implémente l'interface de stratégie — aucune modification du code existant n'est requise.
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine();
String style = scanner.nextLine();
// TODO: Créer une instance de TextEditor
// TODO: Appeler publishText avec le texte d'entrée (avant de définir un formateur)
// TODO: En fonction de l'entrée style ("upper", "lower", ou "title"),
// définir le formateur approprié et appeler à nouveau publishText
}
}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 externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur