Menu
Coddy logo textTech

Pattern Template Method

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 99 di 104.

Il pattern Template Method definisce lo scheletro di un algoritmo in una classe base, consentendo alle sottoclassi di sovrascrivere passaggi specifici senza modificare la struttura complessiva dell'algoritmo. A differenza di Strategy, che sostituisce interi algoritmi, Template Method mantiene fisso l'algoritmo consentendo di personalizzare i singoli passaggi.

La classe base implementa il metodo template (l’algoritmo) e chiama metodi astratti o virtuali che le sottoclassi devono fornire:

#include <iostream>

class DataProcessor {
public:
    // Metodo template - definisce la struttura dell'algoritmo
    void process() {
        loadData();
        processData();
        saveResults();
    }
    
    virtual ~DataProcessor() = default;
    
protected:
    virtual void loadData() = 0;      // Deve essere implementato
    virtual void processData() = 0;   // Deve essere implementato
    
    // Hook - ridefinizione facoltativa con comportamento predefinito
    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();  // Usa saveResults predefinito
    
    JSONProcessor json;
    json.process(); // Usa saveResults personalizzato
}

Il metodo process() è il metodo modello: definisce la sequenza fissa di passaggi. Le sottoclassi implementano loadData() e processData() in modo diverso, ma l’ordine non cambia mai. Il metodo saveResults() è un «hook»: ha un’implementazione predefinita che le sottoclassi possono facoltativamente sovrascrivere.

Usa Template Method quando hai un algoritmo con passaggi invarianti ma hai bisogno di flessibilità in operazioni specifiche, oppure quando vuoi evitare la duplicazione del codice tra classi simili.

challenge icon

Sfida

Facile

Creiamo un sistema di generazione di report usando il pattern Template Method. Creerai un framework in cui diversi tipi di report (come i report sulle vendite e quelli sull'inventario) seguono lo stesso processo di generazione, ma ogni tipo di report personalizza passaggi specifici. È uno scenario perfetto per il Template Method: il flusso di lavoro complessivo rimane fisso, mentre i singoli passaggi variano.

Organizzerai il codice in tre file:

  • ReportGenerator.h: definisci la classe base astratta con il metodo template.

    Crea una classe ReportGenerator che definisca lo scheletro dell'algoritmo di generazione dei report. Il tuo metodo template generateReport() dovrebbe eseguire questi passaggi nell'ordine indicato:

    1. gatherData(): virtuale pura, deve essere implementata dalle sottoclassi
    2. formatReport(): virtuale pura, deve essere implementata dalle sottoclassi
    3. addHeader(): un hook con comportamento predefinito che stampa --- Report ---
    4. printReport(): virtuale pura, deve essere implementata dalle sottoclassi

    Il metodo addHeader() funge da hook che le sottoclassi possono, facoltativamente, sovrascrivere per personalizzare l'intestazione.

  • Reports.h: implementa due generatori di report concreti.

    Crea una classe SalesReport che:

    • gatherData() stampa Gathering sales data from database
    • formatReport() stampa Formatting sales figures
    • printReport() stampa Sales Total: $[amount], dove amount viene passato al costruttore

    Crea una classe InventoryReport che:

    • gatherData() stampa Scanning inventory records
    • formatReport() stampa Organizing inventory by category
    • addHeader() sovrascrive l'hook per stampare === Inventory Report ===
    • printReport() stampa Items in stock: [count], dove count viene passato al costruttore

    Entrambe le classi dovrebbero accettare i rispettivi valori (amount o count) tramite i propri costruttori.

  • main.cpp: mostra il pattern Template Method.

    Leggi due valori in input:

    1. Importo delle vendite (intero)
    2. Quantità di articoli in inventario (intero)

    Crea un SalesReport con l'importo delle vendite e generane il report. Poi crea un InventoryReport con la quantità di articoli in inventario e generane il report. Stampa una riga vuota tra i due report per una maggiore leggibilità.

Ad esempio, con gli input 15000 e 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

Con gli input 8500 e 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

Nota come entrambi i report seguono esattamente la stessa sequenza di passaggi definita in generateReport(), ma ciascuno li implementa in modo diverso. Inoltre, InventoryReport mostra come sovrascrivere il metodo hook per personalizzare l'intestazione, mentre SalesReport usa quella predefinita. Ecco il pattern Template Method in azione: la struttura dell'algoritmo è fissata nella classe base, ma i dettagli sono flessibili.

Provalo tu

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

using namespace std;

int main() {
    // Leggi i valori di input
    int salesAmount;
    int inventoryCount;
    cin >> salesAmount;
    cin >> inventoryCount;
    
    // TODO: Crea un SalesReport con salesAmount e generarlo
    
    // TODO: Stampa una riga vuota tra i report
    
    // TODO: Crea un InventoryReport con inventoryCount e generarlo
    
    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online