Patron Template Method
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 73 sur 87.
Le Template Method Pattern est un patron de conception comportemental qui définit le squelette d'un algorithme dans une classe de base, permettant aux sous-classes de redéfinir des étapes spécifiques sans changer la structure globale. Considérez cela comme une recette : le processus général de cuisson reste le même, mais les ingrédients ou techniques individuels peuvent varier.
Le patron utilise une classe abstraite avec une méthode template qui appelle une séquence d'étapes. Certaines étapes ont des implémentations par défaut, tandis que d'autres sont abstraites et doivent être implémentées par les sous-classes :
abstract class DataProcessor {
// Méthode template - définit la structure de l'algorithme
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Implémentation par défaut (méthode hook)
void saveData() {
System.out.println("Saving to default location");
}
}
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}
class XMLProcessor extends DataProcessor {
void readData() {
System.out.println("Reading XML file");
}
void processData() {
System.out.println("Parsing XML data");
}
}La méthode template est généralement marquée final pour empêcher les sous-classes de modifier la structure de l'algorithme. Lorsqu'elle est appelée, elle exécute la même séquence pour toutes les sous-classes :
DataProcessor csv = new CSVProcessor();
csv.process();
// Sortie :
// Lecture du fichier CSV
// Analyse des données CSV
// Enregistrement à l'emplacement par défautLe patron de méthode (Template Method Pattern) est idéal lorsque vous avez des algorithmes qui partagent la même structure mais diffèrent dans des étapes spécifiques. Il favorise la réutilisation du code en plaçant la logique commune dans la classe de base tout en permettant la personnalisation par l'héritage.
Défi
FacileConstruisons un système de génération de documents en utilisant le Template Method Pattern ! Vous allez créer un framework où différents types de documents (rapports et factures) suivent le même processus de génération mais personnalisent des étapes spécifiques. C'est parfait pour les scénarios où le flux de travail global est fixe, mais où les détails varient selon le type de document.
Vous organiserez votre code sur quatre fichiers :
DocumentGenerator.java: Créez la classe de base abstraite qui définit la méthode modèle. VotreDocumentGeneratordoit avoir :Une méthode
finalappeléegenerateDocument()qui définit le squelette de l'algorithme en appelant trois étapes dans l'ordre :createHeader(),createBody(), etcreateFooter().Deux méthodes abstraites :
createHeader()etcreateBody()que les sous-classes doivent implémenter.Une méthode hook
createFooter()avec une implémentation par défaut qui affiche--- End of Document ---.ReportGenerator.java: Créez une sous-classe concrète pour générer des rapports. Elle doit prendre un titre de rapport (String) via son constructeur.La méthode
createHeader()affiche=== REPORT: [title] ===La méthode
createBody()afficheReport content goes here...Utilisez le pied de page par défaut hérité.
InvoiceGenerator.java: Créez une autre sous-classe concrète pour générer des factures. Elle doit prendre un nom de client (String) et un montant (double) via son constructeur.La méthode
createHeader()affiche*** INVOICE ***La méthode
createBody()afficheCustomer: [name]sur une ligne, puisAmount Due: $[amount]sur la ligne suivante (formatez le montant avec deux décimales).Surchargez
createFooter()pour afficherThank you for your business!Main.java: Rassemblez votre système de méthode modèle ! Vous recevrez trois entrées : un titre de rapport (String), un nom de client (String) et un montant de facture (double).Créez un
ReportGeneratoravec le titre et appelezgenerateDocument(). Affichez une ligne vide pour la séparation. Ensuite, créez unInvoiceGeneratoravec le nom du client et le montant, et appelezgenerateDocument().
Vous recevrez trois entrées dans l'ordre : le titre du rapport (String), le nom du client (String) et le montant de la facture (double).
Par exemple, avec les entrées Q4 Sales, Acme Corp, et 1500.00, votre sortie serait :
=== REPORT: Q4 Sales ===
Report content goes here...
--- End of Document ---
*** INVOICE ***
Customer: Acme Corp
Amount Due: $1500.00
Thank you for your business!Remarquez comment les deux types de documents suivent le même processus en trois étapes défini dans la méthode modèle, mais chacun personnalise les étapes différemment. Le ReportGenerator utilise le pied de page par défaut tandis que InvoiceGenerator fournit le sien — c'est toute la puissance des méthodes hook dans le Template Method Pattern !
Aide-mémoire
Le Template Method Pattern (patron de méthode de base) est un patron de conception comportemental qui définit le squelette d'un algorithme dans une classe de base, permettant aux sous-classes de redéfinir certaines étapes spécifiques sans modifier la structure globale.
Le patron utilise une classe abstraite avec une méthode de base (template method) qui appelle une séquence d'étapes. Certaines étapes ont des implémentations par défaut, tandis que d'autres sont abstraites et doivent être implémentées par les sous-classes :
abstract class DataProcessor {
// Méthode de base - définit la structure de l'algorithme
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Implémentation par défaut (méthode crochet)
void saveData() {
System.out.println("Saving to default location");
}
}Les sous-classes concrètes implémentent les méthodes abstraites :
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}La méthode de base est marquée final pour empêcher les sous-classes de modifier la structure de l'algorithme. Lorsqu'elle est appelée, elle exécute la même séquence pour toutes les sous-classes :
DataProcessor csv = new CSVProcessor();
csv.process();
// Output:
// Reading CSV file
// Parsing CSV data
// Saving to default locationCaractéristiques clés :
- La méthode de base est
finalet définit la structure de l'algorithme - Les méthodes abstraites doivent être implémentées par les sous-classes
- Les méthodes crochets (hook methods) fournissent des implémentations par défaut qui peuvent être éventuellement redéfinies
- Favorise la réutilisation du code en plaçant la logique commune dans la classe de base
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire les entrées
String reportTitle = scanner.nextLine();
String customerName = scanner.nextLine();
double invoiceAmount = scanner.nextDouble();
// TODO: Créer un ReportGenerator avec le titre et appeler generateDocument()
// TODO: Afficher une ligne vide pour la séparation
// TODO: Créer un InvoiceGenerator avec le nom du client et le montant, et appeler generateDocument()
}
}
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