Padrão Template Method
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 73 de 87.
O Padrão Template Method é um padrão de projeto comportamental que define o esqueleto de um algoritmo em uma classe base, permitindo que as subclasses sobrescrevam etapas específicas sem alterar a estrutura geral. Pense nisso como uma receita: o processo geral de cozimento permanece o mesmo, mas ingredientes ou técnicas individuais podem variar.
O padrão usa uma classe abstrata com um método template que chama uma sequência de passos. Alguns passos possuem implementações padrão, enquanto outros são abstratos e devem ser implementados por subclasses:
abstract class DataProcessor {
// Método template - define a estrutura do algoritmo
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Implementação padrão (método 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");
}
}O método template é tipicamente marcado como final para evitar que subclasses alterem a estrutura do algoritmo. Quando chamado, ele executa a mesma sequência para todas as subclasses:
DataProcessor csv = new CSVProcessor();
csv.process();
// Saída:
// Lendo arquivo CSV
// Analisando dados CSV
// Salvando no local padrãoO padrão Template Method é ideal quando você tem algoritmos que compartilham a mesma estrutura, mas diferem em etapas específicas. Ele promove a reutilização de código ao colocar a lógica comum na classe base, permitindo a customização por meio de herança.
Desafio
FácilVamos construir um sistema de geração de documentos usando o Template Method Pattern! Você criará uma estrutura onde diferentes tipos de documentos (relatórios e faturas) seguem o mesmo processo de geração, mas personalizam etapas específicas. Isso é perfeito para cenários onde o fluxo de trabalho geral é fixo, mas os detalhes variam de acordo com o tipo de documento.
Você organizará seu código em quatro arquivos:
DocumentGenerator.java: Crie a classe base abstrata que define o método template. SeuDocumentGeneratordeve ter:Um método
finalchamadogenerateDocument()que define o esqueleto do algoritmo chamando três etapas em ordem:createHeader(),createBody()ecreateFooter().Dois métodos abstratos:
createHeader()ecreateBody()que as subclasses devem implementar.Um método gancho (hook)
createFooter()com uma implementação padrão que imprime--- End of Document ---.ReportGenerator.java: Crie uma subclasse concreta para gerar relatórios. Ela deve receber um título de relatório (String) através de seu construtor.O método
createHeader()imprime=== REPORT: [title] ===O método
createBody()imprimeReport content goes here...Use o rodapé padrão herdado.
InvoiceGenerator.java: Crie outra subclasse concreta para gerar faturas. Ela deve receber um nome de cliente (String) e um valor (double) através de seu construtor.O método
createHeader()imprime*** INVOICE ***O método
createBody()imprimeCustomer: [name]em uma linha, e depoisAmount Due: $[amount]na linha seguinte (formate o valor com duas casas decimais).Sobrescreva
createFooter()para imprimirThank you for your business!Main.java: Reúna seu sistema de método template! Você receberá três entradas: um título de relatório (String), um nome de cliente (String) e um valor de fatura (double).Crie um
ReportGeneratorcom o título e chamegenerateDocument(). Imprima uma linha vazia para separação. Em seguida, crie umInvoiceGeneratorcom o nome do cliente e o valor, e chamegenerateDocument().
Você receberá três entradas em ordem: título do relatório (String), nome do cliente (String) e valor da fatura (double).
Por exemplo, com as entradas Q4 Sales, Acme Corp e 1500.00, sua saída seria:
=== REPORT: Q4 Sales ===
Report content goes here...
--- End of Document ---
*** INVOICE ***
Customer: Acme Corp
Amount Due: $1500.00
Thank you for your business!Observe como ambos os tipos de documentos seguem o mesmo processo de três etapas definido no método template, mas cada um personaliza as etapas de forma diferente. O ReportGenerator usa o rodapé padrão, enquanto o InvoiceGenerator fornece o seu próprio — este é o poder dos métodos gancho (hook methods) no Template Method Pattern!
Folha de consulta
O Padrão Template Method é um padrão de projeto comportamental que define o esqueleto de um algoritmo em uma classe base, permitindo que as subclasses sobrescrevam passos específicos sem alterar a estrutura geral.
O padrão utiliza uma classe abstrata com um método template que chama uma sequência de passos. Alguns passos possuem implementações padrão, enquanto outros são abstratos e devem ser implementados pelas subclasses:
abstract class DataProcessor {
// Método template - define a estrutura do algoritmo
public final void process() {
readData();
processData();
saveData();
}
abstract void readData();
abstract void processData();
// Implementação padrão (método gancho)
void saveData() {
System.out.println("Saving to default location");
}
}Subclasses concretas implementam os métodos abstratos:
class CSVProcessor extends DataProcessor {
void readData() {
System.out.println("Reading CSV file");
}
void processData() {
System.out.println("Parsing CSV data");
}
}O método template é marcado como final para evitar que as subclasses alterem a estrutura do algoritmo. Quando chamado, ele executa a mesma sequência para todas as subclasses:
DataProcessor csv = new CSVProcessor();
csv.process();
// Saída:
// Reading CSV file
// Parsing CSV data
// Saving to default locationPrincipais características:
- O método template é
finale define a estrutura do algoritmo - Métodos abstratos devem ser implementados pelas subclasses
- Métodos gancho (hook methods) fornecem implementações padrão que podem ser opcionalmente sobrescritas
- Promove a reutilização de código ao colocar a lógica comum na classe base
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler entradas
String reportTitle = scanner.nextLine();
String customerName = scanner.nextLine();
double invoiceAmount = scanner.nextDouble();
// TODO: Criar um ReportGenerator com o título e chamar generateDocument()
// TODO: Imprimir uma linha vazia para separação
// TODO: Criar um InvoiceGenerator com o nome do cliente e o valor, e chamar generateDocument()
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator