O padrão de projeto Template Method (Método Modelo) é um padrão comportamental que define o esqueleto de um algoritmo em uma operação, adiando a implementação de alguns passos para as subclasses. Ele permite que as classes derivadas redefinam etapas específicas de um algoritmo sem alterar a sua estrutura geral e a ordem de execução.
Em desenvolvimento orientado a objetos, é comum encontrar cenários onde a sequência de execução de um processo é rígida e bem definida, mas a implementação de etapas individuais pode variar dependendo do contexto. O Template Method resolve essa questão encapsulando a lógica invariável em uma classe base (normalmente abstrata) e delegando as partes variáveis para as subclasses através de métodos abstratos ou métodos gancho (hook methods).
Cenários de Aplicação
- Quando múltiplas subclasses possuem métodos com a mesma estrutura de execução e lógica similar, o que gera duplicação de código.
- Em algoritmos complexos onde o núcleo do processamento deve ser imutável, mas os detalhes periféricos ou específicos de domínio precisam ser implementados pelas subclasses.
- Durante processos de refatoração, para extrair comportamentos idênticos espalhados por várias classes e consolidá-los em uma superclasse, aplicando o Princípio de Hollywood ("Não nos chame, nós chamaremos você").
Implementação Prática
Para ilustrar o conceito, utilizaremos um pipeline de migração de dados. O fluxo padrão e imutável envolve: estabelecer conexão, extrair os dados, transformar e carregar no destino, e encerrar a conexão. A ordem é estrita, mas as regras de extração e transformação mudam de acordo com a fonte de dados.
/**
* Classe abstrata que define o template do processo de migração.
*/
public abstract class DataMigrationPipeline {
protected void establishConnection() {
System.out.println("1. Estabelecendo conexão com o banco de dados...");
}
// Métodos abstratos que devem ser implementados pelas subclasses
protected abstract void extractData();
protected abstract void transformAndLoad();
protected void closeConnection() {
System.out.println("4. Encerrando conexão com o banco de dados.");
}
/**
* O método template é marcado como final para impedir que subclasses
* alterem a estrutura do algoritmo.
*/
public final void executeMigration() {
establishConnection();
extractData();
transformAndLoad();
closeConnection();
}
}
Agora, criamos uma implementação concreta para migrar dados de um sistema legado para um formato JSON:
/**
* Implementação concreta para migração de dados legados.
*/
public class LegacyToJsonMigration extends DataMigrationPipeline {
@Override
protected void extractData() {
System.out.println("2. Extraindo registros do sistema legado...");
}
@Override
protected void transformAndLoad() {
System.out.println("3. Transformando dados e salvando em arquivos JSON...");
}
}
Por fim, a classe cliente que executa o pipeline:
/**
* Classe executora para demonstrar o padrão.
*/
public class MigrationRunner {
public static void main(String[] args) {
DataMigrationPipeline migrationTask = new LegacyToJsonMigration();
// O cliente chama o método template, sem se preocupar com os passos internos.
migrationTask.executeMigration();
}
}
Uso em Frameworks
O padrão Template Method é onipresente no design de frameworks e bibliotecas de alto nível. Um exemplo clássico ocorre no ciclo de vida de renderização de interfaces gráficas, como o processo de measure, layout e draw nas Views do Android. O framewokr controla a ordem estrita dessas chamadas, enquanto os desenvolvedores estendem as classes base e sobrescrevem métodos específicos para personalizar a aparência e o comportamento dos componentes.