Patrón Template Method
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 73 de 87.
El Patrón Template Method es un patrón de diseño de comportamiento que define el esqueleto de un algoritmo en una clase base, permitiendo que las subclases sobrescriban pasos específicos sin cambiar la estructura general. Piénselo como una receta: el proceso general de cocción sigue siendo el mismo, pero los ingredientes o técnicas individuales pueden variar.
El patrón utiliza una clase abstracta con un método de plantilla que llama a una secuencia de pasos. Algunos pasos tienen implementaciones predeterminadas, mientras que otros son abstractos y deben ser implementados por las subclases:
abstract class DataProcessor {
// Método de plantilla - define la estructura del algoritmo
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Implementación por defecto (método de gancho)
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");
}
}El método de plantilla suele marcarse como final para evitar que las subclases alteren la estructura del algoritmo. Cuando se llama, ejecuta la misma secuencia para todas las subclases:
DataProcessor csv = new CSVProcessor();
csv.process();
// Salida:
// Leyendo archivo CSV
// Analizando datos CSV
// Guardando en la ubicación predeterminadaEl patrón Template Method es ideal cuando tienes algoritmos que comparten la misma estructura pero difieren en pasos específicos. Promueve la reutilización de código al colocar la lógica común en la clase base mientras permite la personalización a través de la herencia.
Desafío
Fácil¡Vamos a construir un sistema de generación de documentos utilizando el Patrón Template Method! Crearás un marco de trabajo donde diferentes tipos de documentos (informes y facturas) siguen el mismo proceso de generación pero personalizan pasos específicos. Esto es perfecto para escenarios donde el flujo de trabajo general es fijo, pero los detalles varían según el tipo de documento.
Organizarás tu código en cuatro archivos:
DocumentGenerator.java: Crea la clase base abstracta que define el método de plantilla. TuDocumentGeneratordebe tener:Un método
finalllamadogenerateDocument()que define el esqueleto del algoritmo llamando a tres pasos en orden:createHeader(),createBody()ycreateFooter().Dos métodos abstractos:
createHeader()ycreateBody()que las subclases deben implementar.Un método de gancho (hook)
createFooter()con una implementación por defecto que imprime--- End of Document ---.ReportGenerator.java: Crea una subclase concreta para generar informes. Debe recibir un título de informe (String) a través de su constructor.El método
createHeader()imprime=== REPORT: [title] ===El método
createBody()imprimeReport content goes here...Utiliza el pie de página predeterminado heredado.
InvoiceGenerator.java: Crea otra subclase concreta para generar facturas. Debe recibir un nombre de cliente (String) y un monto (double) a través de su constructor.El método
createHeader()imprime*** INVOICE ***El método
createBody()imprimeCustomer: [name]en una línea, luegoAmount Due: $[amount]en la siguiente línea (formatea el monto a dos decimales).Sobrescribe
createFooter()para imprimirThank you for your business!Main.java: ¡Une tu sistema de método de plantilla! Recibirás tres entradas: un título de informe (String), un nombre de cliente (String) y un monto de factura (double).Crea un
ReportGeneratorcon el título y llama agenerateDocument(). Imprime una línea vacía para separación. Luego crea unInvoiceGeneratorcon el nombre del cliente y el monto, y llama agenerateDocument().
Recibirás tres entradas en orden: título del informe (String), nombre del cliente (String) y monto de la factura (double).
Por ejemplo, con las entradas Q4 Sales, Acme Corp y 1500.00, tu salida sería:
=== REPORT: Q4 Sales ===
Report content goes here...
--- End of Document ---
*** INVOICE ***
Customer: Acme Corp
Amount Due: $1500.00
Thank you for your business!Observa cómo ambos tipos de documentos siguen el mismo proceso de tres pasos definido en el método de plantilla, pero cada uno personaliza los pasos de manera diferente. El ReportGenerator utiliza el pie de página predeterminado mientras que InvoiceGenerator proporciona el suyo propio; ¡este es el poder de los métodos de gancho en el Patrón Template Method!
Hoja de referencia
El Patrón de Método de Plantilla es un patrón de diseño de comportamiento que define el esqueleto de un algoritmo en una clase base, permitiendo que las subclases sobrescriban pasos específicos sin cambiar la estructura general.
El patrón utiliza una clase abstracta con un método de plantilla que llama a una secuencia de pasos. Algunos pasos tienen implementaciones por defecto, mientras que otros son abstractos y deben ser implementados por las subclases:
abstract class DataProcessor {
// Método de plantilla - define la estructura del algoritmo
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Implementación por defecto (método de gancho)
void saveData() {
System.out.println("Saving to default location");
}
}Las subclases concretas implementan los métodos abstractos:
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}El método de plantilla está marcado como final para evitar que las subclases alteren la estructura del algoritmo. Cuando se llama, ejecuta la misma secuencia para todas las subclases:
DataProcessor csv = new CSVProcessor();
csv.process();
// Salida:
// Reading CSV file
// Parsing CSV data
// Saving to default locationCaracterísticas clave:
- El método de plantilla es
finaly define la estructura del algoritmo - Los métodos abstractos deben ser implementados por las subclases
- Los métodos de gancho proporcionan implementaciones por defecto que pueden ser sobrescritas opcionalmente
- Promueve la reutilización de código al colocar la lógica común en la clase base
Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leer las entradas
String reportTitle = scanner.nextLine();
String customerName = scanner.nextLine();
double invoiceAmount = scanner.nextDouble();
// TODO: Crea un ReportGenerator con el título y llama a generateDocument()
// TODO: Imprime una línea vacía para separar
// TODO: Crea un InvoiceGenerator con el nombre del cliente y el monto, y llama a generateDocument()
}
}
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
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator