Menu
Coddy logo textTech

Pattern Méthode Modèle

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 99 sur 104.

Le patron Template Method définit le squelette d’un algorithme dans une classe de base, en permettant aux sous-classes de redéfinir des étapes spécifiques sans modifier la structure globale de l’algorithme. Contrairement à Strategy, qui remplace des algorithmes entiers, Template Method conserve l’algorithme fixe tout en permettant de personnaliser des étapes individuelles.

La classe de base implémente la méthode modèle (l’algorithme) et appelle des méthodes abstraites ou virtuelles que les sous-classes doivent fournir :

#include <iostream>

class DataProcessor {
public:
    // Méthode template - définit le squelette de l'algorithme
    void process() {
        loadData();
        processData();
        saveResults();
    }
    
    virtual ~DataProcessor() = default;
    
protected:
    virtual void loadData() = 0;      // Doit être implémenté
    virtual void processData() = 0;   // Doit être implémenté
    
    // Hook - redéfinition optionnelle avec comportement par défaut
    virtual void saveResults() {
        std::cout << "Saving to default location\n";
    }
};

class CSVProcessor : public DataProcessor {
protected:
    void loadData() override {
        std::cout << "Loading CSV file\n";
    }
    void processData() override {
        std::cout << "Parsing CSV data\n";
    }
};

class JSONProcessor : public DataProcessor {
protected:
    void loadData() override {
        std::cout << "Loading JSON file\n";
    }
    void processData() override {
        std::cout << "Parsing JSON data\n";
    }
    void saveResults() override {
        std::cout << "Saving to cloud storage\n";
    }
};

int main() {
    CSVProcessor csv;
    csv.process();  // Utilise saveResults par défaut
    
    JSONProcessor json;
    json.process(); // Utilise saveResults personnalisé
}

La méthode process() est la méthode modèle : elle définit la séquence fixe des étapes. Les sous-classes implémentent loadData() et processData() différemment, mais l’ordre ne change jamais. La méthode saveResults() est un « hook » : elle possède une implémentation par défaut que les sous-classes peuvent éventuellement redéfinir.

Utilisez Template Method lorsque vous avez un algorithme comportant des étapes invariantes, mais que vous avez besoin de flexibilité pour certaines opérations, ou lorsque vous souhaitez éviter la duplication de code entre des classes similaires.

challenge icon

Défi

Facile

Construisons un système de génération de rapports utilisant le patron Template Method. Vous allez créer un framework dans lequel différents types de rapports (comme les rapports de ventes et les rapports d’inventaire) suivent le même processus de génération, mais chaque type de rapport personnalise certaines étapes. C’est un scénario parfait pour Template Method : le flux de travail global reste fixe tandis que les étapes individuelles varient.

Vous allez organiser votre code dans trois fichiers :

  • ReportGenerator.h : définir la classe de base abstraite avec la méthode modèle.

    Créez une classe ReportGenerator qui définit la structure de l’algorithme de génération de rapports. Votre méthode modèle generateReport() doit exécuter ces étapes dans l’ordre :

    1. gatherData() : virtuelle pure, doit être implémentée par les sous-classes
    2. formatReport() : virtuelle pure, doit être implémentée par les sous-classes
    3. addHeader() : un hook avec un comportement par défaut qui affiche --- Report ---
    4. printReport() : virtuelle pure, doit être implémentée par les sous-classes

    La méthode addHeader() sert de hook que les sous-classes peuvent éventuellement redéfinir pour personnaliser l’en-tête.

  • Reports.h : implémenter deux générateurs de rapports concrets.

    Créez une classe SalesReport qui :

    • gatherData() affiche Gathering sales data from database
    • formatReport() affiche Formatting sales figures
    • printReport() affiche Sales Total: $[amount], où amount est transmis au constructeur

    Créez une classe InventoryReport qui :

    • gatherData() affiche Scanning inventory records
    • formatReport() affiche Organizing inventory by category
    • addHeader() redéfinit le hook pour afficher === Inventory Report ===
    • printReport() affiche Items in stock: [count], où count est transmis au constructeur

    Les deux classes doivent accepter leurs valeurs respectives (amount ou count) via leurs constructeurs.

  • main.cpp : démontrer le patron Template Method.

    Lisez deux entrées :

    1. Montant des ventes (entier)
    2. Nombre d’articles en inventaire (entier)

    Créez un SalesReport avec le montant des ventes et générez-le. Créez ensuite un InventoryReport avec le nombre d’articles en inventaire et générez-le. Affichez une ligne vide entre les deux rapports pour améliorer la lisibilité.

Par exemple, avec les entrées 15000 et 250 :

Gathering sales data from database
Formatting sales figures
--- Report ---
Sales Total: $15000

Scanning inventory records
Organizing inventory by category
=== Inventory Report ===
Items in stock: 250

Avec les entrées 8500 et 120 :

Gathering sales data from database
Formatting sales figures
--- Report ---
Sales Total: $8500

Scanning inventory records
Organizing inventory by category
=== Inventory Report ===
Items in stock: 120

Remarquez que les deux rapports suivent exactement la même séquence d’étapes définie dans generateReport(), mais que chacun implémente ces étapes différemment. InventoryReport montre également la redéfinition de la méthode hook pour personnaliser l’en-tête, tandis que SalesReport utilise le comportement par défaut. Voici le patron Template Method en action : la structure de l’algorithme est verrouillée dans la classe de base, mais les détails restent flexibles.

Essayez vous-même

#include <iostream>
#include "Reports.h"

using namespace std;

int main() {
    // Lire les entrées
    int salesAmount;
    int inventoryCount;
    cin >> salesAmount;
    cin >> inventoryCount;
    
    // TODO: Créer un SalesReport avec salesAmount et le générer
    
    // TODO: Afficher une ligne vide entre les rapports
    
    // TODO: Create an InventoryReport with inventoryCount and generate it
    
    return 0;
}
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 Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne