Padrão Template Method
Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 78 de 91.
O Template Method Pattern é um padrão de projeto comportamental que define o esqueleto de um algoritmo em uma classe base, permitindo que subclasses sobrescrevam etapas específicas sem alterar a estrutura geral. A classe base controla o fluxo de trabalho, enquanto as subclasses customizam partes individuais.
Considere construir diferentes tipos de documentos.
Cada documento segue o mesmo processo: criar cabeçalho, adicionar conteúdo, criar rodapé. Mas as especificidades de cada etapa variam de acordo com o tipo de documento. O template method define essa sequência, enquanto as subclasses implementam os detalhes.
<?php
abstract class DocumentGenerator {
// O método template - define a estrutura do algoritmo
public final function generate(): string {
$output = $this->createHeader();
$output .= $this->createContent();
$output .= $this->createFooter();
return $output;
}
// Passos a serem implementados pelas subclasses
abstract protected function createHeader(): string;
abstract protected function createContent(): string;
abstract protected function createFooter(): string;
}
class HtmlDocument extends DocumentGenerator {
protected function createHeader(): string {
return "<html><head></head><body>";
}
protected function createContent(): string {
return "<p>Hello World</p>";
}
protected function createFooter(): string {
return "</body></html>";
}
}
class TextDocument extends DocumentGenerator {
protected function createHeader(): string {
return "=== DOCUMENT ===\n";
}
protected function createContent(): string {
return "Hello World\n";
}
protected function createFooter(): string {
return "=== END ===";
}
}
$html = new HtmlDocument();
echo $html->generate() . "\n";
$text = new TextDocument();
echo $text->generate();
Saída:
<html><head></head><body><p>Hello World</p></body></html>
=== DOCUMENT ===
Hello World
=== END ===Observe a palavra-chave final no método template. Isso impede que subclasses alterem a estrutura do algoritmo. O padrão é ideal quando você tem várias classes que seguem o mesmo fluxo de trabalho, mas diferem nos detalhes de implementação. Adicionar um novo tipo de documento significa criar uma nova subclasse sem tocar no código existente.
Desafio
FácilVamos construir um sistema de geração de relatórios usando o Template Method Pattern. Diferentes tipos de relatórios seguem a mesma estrutura — uma seção de título, uma seção de dados e uma seção de resumo — mas cada tipo de relatório formata essas seções de maneira diferente. O método template definirá este fluxo de trabalho enquanto as subclasses personalizam cada etapa.
Você organizará seu código em quatro arquivos:
ReportGenerator.php— Crie uma classe abstrataReportGeneratorque define o esqueleto do algoritmo de geração de relatório. Sua classe deve:- Aceitar um título de relatório em seu construtor (use a promoção de construtor)
- Ter um método público
finalchamadogenerate(): stringque chama três etapas em ordem:createTitle(),createBody()ecreateSummary(), concatenando seus resultados - Declarar três métodos protegidos abstratos que as subclasses devem implementar:
createTitle(): string,createBody(): stringecreateSummary(): string
HtmlReport.php— Inclua o arquivo ReportGenerator e crie uma classeHtmlReportque o estenda. Este relatório formata a saída como HTML:createTitle()retorna"<h1>" . $this->title . "</h1>"createBody()retorna"<p>Report data goes here</p>"createSummary()retorna"<footer>End of report</footer>"
PlainTextReport.php— Inclua o arquivo ReportGenerator e crie uma classePlainTextReportque o estenda. Este relatório usa formatação de texto simples:createTitle()retorna"### " . $this->title . " ###\n"createBody()retorna"Report data goes here\n"createSummary()retorna"--- End of report ---"
main.php— Inclua ambos os arquivos de relatório. Você receberá duas entradas: um tipo de relatório ("html"ou"text") e um título de relatório.Com base no tipo de relatório, crie o gerador de relatório apropriado com o título fornecido. Chame
generate()e imprima o relatório completo.
O Template Method Pattern garante que todos os relatórios sigam a mesma estrutura de três etapas, permitindo que cada tipo de relatório formate suas seções de forma exclusiva. A palavra-chave final em generate() impede que as subclasses alterem a sequência do algoritmo — elas só podem personalizar as etapas individuais.
Folha de consulta
O Template Method Pattern define o esqueleto de um algoritmo em uma classe base, permitindo que as subclasses substituam etapas específicas sem alterar a estrutura geral.
A classe base contém um template method que controla a sequência do fluxo de trabalho. Este método é normalmente marcado como final para evitar que as subclasses alterem a estrutura do algoritmo.
As subclasses implementam métodos abstratos para personalizar etapas individuais do algoritmo.
<?php
abstract class DocumentGenerator {
// Template method - define a estrutura do algoritmo
public final function generate(): string {
$output = $this->createHeader();
$output .= $this->createContent();
$output .= $this->createFooter();
return $output;
}
// Etapas abstratas para as subclasses implementarem
abstract protected function createHeader(): string;
abstract protected function createContent(): string;
abstract protected function createFooter(): string;
}
class HtmlDocument extends DocumentGenerator {
protected function createHeader(): string {
return "<html><head></head><body>";
}
protected function createContent(): string {
return "<p>Hello World</p>";
}
protected function createFooter(): string {
return "</body></html>";
}
}
$html = new HtmlDocument();
echo $html->generate();
Características principais:
- O template method é marcado como
finalpara evitar a modificação da estrutura do algoritmo - Métodos abstratos definem pontos de personalização para as subclasses
- Ideal quando várias classes seguem o mesmo fluxo de trabalho, mas diferem nos detalhes de implementação
- Adicionar novas variantes requer apenas a criação de novas subclasses sem modificar o código existente
Experimente você mesmo
<?php
require_once 'HtmlReport.php';
require_once 'PlainTextReport.php';
// Ler entrada
$reportType = trim(fgets(STDIN));
$reportTitle = trim(fgets(STDIN));
// TODO: Com base no tipo de relatório ("html" ou "text"),
// crie o gerador de relatório apropriado com o título fornecido
// TODO: Chame generate() e imprima o relatório completo
?>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étodosPropriedadesConstrutor (__construct)Destrutor (__destruct)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Palavra-chave parent::Sobrescrita de MétodoA Palavra-chave finalClasses AbstratasRecapitulação - Hierarquia de Funcionários7Encapsulamento
Público, Protegido, PrivadoModificadores de Acesso em DetalhesGetters e SettersOcultação de InformaçãoPromoção de Construtor (8.0)Recapitulação - Sistema de Registro de Alunos10Conceitos Avançados de POO
Composição vs HerançaInjeção de DependênciaClasses AnônimasEnums (PHP 8.1)Fibers (PHP 8.1)Mergulho Profundo em Clonagem de ObjetosGeradores e Iteradores13Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Repository2Namespaces e Autoloading
Introdução a NamespacesA Palavra-chave usePadrão de Autoloading PSR-4Autoloader do ComposerRecapitulação - Projeto Organizado5Interfaces e Contratos
Introdução a InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesInterface vs Classe AbstrataType Hinting com InterfacesRecapitulação - Calculadora de Formas8Métodos Mágicos
Introdução aos Métodos Mágicos__toString e __debugInfo__get, __set, __isset, __unset__call e __callStatic__clone e Clonagem de Objetos__serialize e __unserializeRecapitulação - Coleção Personalizada11Sistema de Tipos e Tratamento de Erros
Declarações de TiposTipos AnuláveisTipos de União e InterseçãoClasses de ExceçãoHierarquia de Exceções PersonalizadasTry, Catch, FinallyRecapitulação - Validador de Formulário14Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário3Propriedades de Classe
Propriedades de Instância vs EstáticasConstantes em ClassesMétodos e Propriedades EstáticosPropriedades Privadas e ProtegidasPropriedades Readonly (PHP 8.1)Recapitulação - Gerenciador de Conta Bancária6Polimorfismo
Sobrescrita de Métodos RevisitadaPolimorfismo via InterfacesType Hinting e Union TypesLate Static BindingRecapitulação - Processador de Pagamentos9Traits
Introdução a TraitsUsando Múltiplos TraitsResolução de Conflitos de TraitsMétodos Abstratos em TraitsTraits vs Herança12Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy