Menu
Coddy logo textTech

Patrón Template Method

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 99 de 104.

El patrón Template Method define el esqueleto de un algoritmo en una clase base, lo que permite que las subclases redefinan pasos específicos sin cambiar la estructura general del algoritmo. A diferencia de Strategy, que intercambia algoritmos completos, Template Method mantiene fijo el algoritmo y permite personalizar pasos individuales.

La clase base implementa el método plantilla (el algoritmo) y llama a métodos abstractos o virtuales que las subclases deben proporcionar:

#include <iostream>

class DataProcessor {
public:
    // Método plantilla - define el esqueleto del algoritmo
    void process() {
        loadData();
        processData();
        saveResults();
    }
    
    virtual ~DataProcessor() = default;
    
protected:
    virtual void loadData() = 0;      // Debe ser implementado
    virtual void processData() = 0;   // Debe ser implementado
    
    // Hook - sobrescritura opcional con comportamiento por defecto
    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 por defecto
    
    JSONProcessor json;
    json.process(); // Usa saveResults personalizado
}

El método process() es el método plantilla: define la secuencia fija de pasos. Las subclases implementan loadData() y processData() de manera diferente, pero el orden nunca cambia. El método saveResults() es un «hook»: tiene una implementación predeterminada que las subclases pueden sobrescribir opcionalmente.

Usa Template Method cuando tengas un algoritmo con pasos invariantes, pero necesites flexibilidad en operaciones específicas, o cuando quieras evitar la duplicación de código entre clases similares.

challenge icon

Desafío

Fácil

Construyamos un sistema de Generador de informes utilizando el patrón Template Method. Crearás un marco en el que distintos tipos de informes (como informes de ventas e informes de inventario) siguen el mismo proceso de generación, pero cada tipo de informe personaliza pasos específicos. Este es un escenario perfecto para Template Method: el flujo de trabajo general permanece fijo, mientras que los pasos individuales varían.

Organizarás tu código en tres archivos:

  • ReportGenerator.h: Define la clase base abstracta con el método plantilla.

    Crea una clase ReportGenerator que defina el esqueleto del algoritmo de generación de informes. Tu método plantilla generateReport() debe ejecutar estos pasos en orden:

    1. gatherData(): virtual puro, debe ser implementado por las subclases
    2. formatReport(): virtual puro, debe ser implementado por las subclases
    3. addHeader(): un hook con un comportamiento predeterminado que imprime --- Report ---
    4. printReport(): virtual puro, debe ser implementado por las subclases

    El método addHeader() sirve como un hook que las subclases pueden sobrescribir opcionalmente para personalizar el encabezado.

  • Reports.h: Implementa dos generadores de informes concretos.

    Crea una clase SalesReport que:

    • gatherData() imprime Gathering sales data from database
    • formatReport() imprime Formatting sales figures
    • printReport() imprime Sales Total: $[amount], donde amount se pasa al constructor

    Crea una clase InventoryReport que:

    • gatherData() imprime Scanning inventory records
    • formatReport() imprime Organizing inventory by category
    • addHeader() sobrescribe el hook para imprimir === Inventory Report ===
    • printReport() imprime Items in stock: [count], donde count se pasa al constructor

    Ambas clases deben aceptar sus respectivos valores (amount o count) mediante sus constructores.

  • main.cpp: Demuestra el patrón Template Method.

    Lee dos entradas:

    1. Importe de ventas (entero)
    2. Cantidad de inventario (entero)

    Crea un SalesReport con el importe de ventas y genéralo. Después, crea un InventoryReport con la cantidad de inventario y genéralo. Imprime una línea en blanco entre los dos informes para facilitar la lectura.

Por ejemplo, con las entradas 15000 y 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 las entradas 8500 y 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

Observa cómo ambos informes siguen exactamente la misma secuencia de pasos definida en generateReport(), pero cada uno implementa esos pasos de manera diferente. InventoryReport también demuestra cómo sobrescribir el método hook para personalizar el encabezado, mientras que SalesReport utiliza el comportamiento predeterminado. Este es el patrón Template Method en acción: la estructura del algoritmo está fijada en la clase base, pero los detalles son flexibles.

Pruébalo tú mismo

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

using namespace std;

int main() {
    // Leer entradas
    int salesAmount;
    int inventoryCount;
    cin >> salesAmount;
    cin >> inventoryCount;
    
    // TODO: Crea un SalesReport con salesAmount y genéralo
    
    // TODO: Imprime una línea en blanco entre los reportes
    
    // TODO: Create an InventoryReport with inventoryCount and generate it
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online