Pular para o conteúdo
GoF/23 Padrões de Projeto Comportamentais
325
Comportamental escopo de classe

Template Method

Método Modelo

A superclasse fixa o esqueleto; as subclasses preenchem os buracos.

Complexidade simples Frequência de uso moderada
D

Definição

Intenção — palavra por palavra, como o livro define

Definir o esqueleto de um algoritmo em uma operação, postergando alguns passos para as subclasses. Template Method permite que subclasses redefinam certos passos de um algoritmo sem mudar sua estrutura.

E

Exemplo e motivação

Analogia

A planta padrão do condomínio

Todas as casas do condomínio seguem a mesma planta: fundação, estrutura, paredes, telhado, acabamento — nessa ordem, sempre. O comprador escolhe o acabamento e o material das paredes. A sequência das etapas é imutável; o conteúdo de algumas delas, não.

O problema

Vários processos seguem exatamente a mesma sequência de etapas, diferindo apenas em algumas delas. O resultado é código quase duplicado entre classes, com a estrutura repetida por toda parte.

A solução

Quebre o algoritmo em etapas. Coloque na superclasse um método `template` que chama as etapas na ordem correta e é declarado final. Etapas comuns ganham implementação padrão; as que variam viram abstratas ou “hooks” opcionais.

Sintomascomo reconhecer no seu código
  • Três classes com o mesmo método, diferindo em duas linhas.
  • Copiar e colar uma sequência de etapas para criar uma variante.
Na práticaonde ele já existe
  • java.util.AbstractList / AbstractMap
  • javax.servlet.http.HttpServlet — doGet, doPost são hooks
  • Métodos de ciclo de vida de frameworks (setUp/tearDown de testes)
D

Diagrama

«abstrata»MineradorDeDados+ minerar() «final»# abrir()*# extrair()*# analisar()# aoTerminar() «hook»MineradorCSV# abrir()# extrair()MineradorPDF# abrir()# extrair()MineradorAPI# abrir()# aoTerminar()
Fig. 22 — Template Method herda / implementa cria usa / contém
Ver este diagrama sendo desenhado, traço a traço
Participantes
AbstractClass
Define o método template (a ordem fixa) e declara as etapas.
ConcreteClass
Implementa as etapas abstratas e, opcionalmente, sobrescreve hooks.
Hook
Etapa com implementação vazia/padrão que a subclasse pode ou não sobrescrever.
A

Aplicabilidade

Use quando
  • Clientes precisam estender só partes específicas de um algoritmo, não sua estrutura.
  • Várias classes têm algoritmos quase idênticos, com pequenas diferenças.
Evite quando
  • Você precisa trocar o algoritmo inteiro em tempo de execução — use Strategy.
  • A hierarquia de herança já está profunda demais.
C

Consequências

A favor
  • Elimina duplicação: a estrutura do algoritmo existe uma vez só.
  • Deixa os clientes sobrescrever apenas partes bem definidas.
  • A ordem das etapas fica protegida contra alterações acidentais.
Contra
  • Limita a flexibilidade ao esqueleto pré-definido.
  • Viola o Princípio de Substituição de Liskov se uma subclasse suprimir uma etapa padrão.
  • Quanto mais etapas, mais difícil de manter.
  • Herança acopla fortemente: a subclasse depende de detalhes internos da superclasse.
Apêndice

Código

Listagem 22 Pipeline de importação com etapas fixas e variáveis
class ImportadorDeDados {
  // ── O TEMPLATE METHOD: a ordem é lei, ninguém sobrescreve ──
  importar(caminho) {
    const bruto      = this.ler(caminho);            // ① abstrato
    const registros  = this.analisar(bruto);         // ② abstrato
    const validos    = registros.filter(r => this.validar(r));  // ③ padrão, sobrescrevível
    const finais     = validos.map(r => this.transformar(r));   // ④ hook (identidade)
    this.persistir(finais);                          // ⑤ padrão
    this.aoConcluir(finais);                         // ⑥ hook (vazio)
    return { lidos: registros.length, importados: finais.length };
  }

  // ── Etapas OBRIGATÓRIAS (abstratas) ─────────────────
  ler(caminho)      { throw new Error('subclasse deve implementar ler()'); }
  analisar(bruto)   { throw new Error('subclasse deve implementar analisar()'); }

  // ── Etapas com PADRÃO (podem ser sobrescritas) ──────
  validar(r)     { return r != null && Object.keys(r).length > 0; }
  persistir(rs)  { console.log(`💾 gravando ${rs.length} registros`); }

  // ── HOOKS: existem só para serem opcionalmente estendidos ──
  transformar(r) { return r; }
  aoConcluir(rs) { /* vazio de propósito */ }
}

class ImportadorCSV extends ImportadorDeDados {
  ler(c)        { return 'nome,idade\nAna,30\nBruno,\nCarla,41'; }
  analisar(txt) {
    const [cab, ...linhas] = txt.split('\n');
    const cols = cab.split(',');
    return linhas.map(l => Object.fromEntries(l.split(',').map((v, i) => [cols[i], v])));
  }
  validar(r)    { return super.validar(r) && r.idade !== ''; }   // estende o padrão
  transformar(r){ return { ...r, idade: Number(r.idade) }; }
}

class ImportadorJSON extends ImportadorDeDados {
  ler(c)        { return '[{"nome":"Dan","idade":22}]'; }
  analisar(txt) { return JSON.parse(txt); }
  aoConcluir(rs){ console.log('📣 webhook disparado'); }          // usa o hook
}

console.log(new ImportadorCSV().importar('x.csv'));    // { lidos: 3, importados: 2 }
console.log(new ImportadorJSON().importar('x.json'));  // 📣 webhook … { lidos: 1, importados: 1 }
Apêndice

Relações

alternativa a
Strategy
Template Method: herança, em tempo de compilação, partes do algoritmo. Strategy: composição, em tempo de execução, o algoritmo todo.
costuma andar junto
Factory Method
Factory Method é frequentemente uma etapa dentro de um Template Method.
parecido / fácil de confundir
Builder
Ambos definem uma sequência de etapas; Builder usa composição, Template Method usa herança.
Apêndice

Verificação

Questãoa resposta está marcada

O que é um “hook” em Template Method?

  1. Uma etapa com implementação vazia ou padrão, que a subclasse pode sobrescrever mas não precisa
  2. Um método que a subclasse é obrigada a implementar
  3. Um callback registrado em tempo de execução
  4. O método que define a ordem das etapas

Hooks são pontos de extensão opcionais. Etapas abstratas são obrigatórias; o método template é o que define a ordem e normalmente é final.