Padrão Template Method
Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 59 de 70.
O padrão Template Method é um padrão 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. A classe base controla o fluxo de trabalho, enquanto as classes derivadas customizam partes individuais.
Este padrão utiliza herança e métodos abstratos. A classe base contém um "template method" que chama uma sequência de passos, alguns dos quais são abstratos e devem ser implementados pelas subclasses:
public abstract class DataProcessor
{
// Template method - define a estrutura do algoritmo
public void Process()
{
ReadData();
ProcessData();
SaveData();
}
protected abstract void ReadData();
protected abstract void ProcessData();
protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}
public class CsvProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading CSV file");
protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}
public class JsonProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading JSON file");
protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
protected override void SaveData() => Console.WriteLine("Saving to cloud");
}Cada subclasse fornece sua própria implementação, enquanto a classe base impõe a ordem das operações:
DataProcessor csv = new CsvProcessor();
csv.Process();
// Lendo arquivo CSV
// Analisando dados CSV
// Salvando no local padrão
DataProcessor json = new JsonProcessor();
json.Process();
// Lendo arquivo JSON
// Analisando dados JSON
// Salvando na nuvemO padrão Template Method é ideal quando múltiplas classes compartilham a mesma estrutura de algoritmo, mas diferem em passos específicos. Ele promove a reutilização de código ao colocar a lógica comum na classe base, permitindo flexibilidade por meio de métodos que podem ser sobrescritos.
Desafio
FácilVamos construir um sistema de geração de relatórios usando o padrão Template Method. Diferentes tipos de relatórios (como relatórios de vendas e relatórios de estoque) compartilham a mesma estrutura geral - todos precisam coletar dados, formatá-los e gerar o resultado - mas cada tipo de relatório lida com essas etapas de forma diferente.
Você organizará seu código em três arquivos:
ReportGenerator.cs: Crie uma classe abstrataReportGeneratorno namespaceReporting. Esta classe base define o esqueleto do algoritmo de geração de relatório através de um método template chamadoGenerate(). O método deve chamar três etapas em ordem:GatherData(),FormatReport()eOutputReport(). TorneGatherData()eFormatReport()abstratos (cada tipo de relatório os implementará de forma diferente), enquantoOutputReport()deve ser um método virtual com uma implementação padrão que imprimeSending to default printer.ConcreteReports.cs: Crie duas classes de relatório concretas no mesmo namespace que herdam deReportGenerator:SalesReport- implementaGatherData()para imprimirCollecting sales data from databaseeFormatReport()para imprimirFormatting as sales summaryInventoryReport- implementaGatherData()para imprimirScanning warehouse inventory,FormatReport()para imprimirFormatting as inventory list, e sobrescreveOutputReport()para imprimirSending to warehouse manager
Program.cs: Reúna tudo criando instâncias de relatório e gerando-as. O método template garante que cada relatório siga o mesmo processo de três etapas, mas o comportamento específico de cada etapa varia de acordo com o tipo de relatório.
Você receberá uma entrada:
- O tipo de relatório:
salesouinventory
Crie o gerador de relatório apropriado com base na entrada e chame seu método Generate().
Por exemplo, se a entrada for sales, a saída deve ser:
Collecting sales data from database
Formatting as sales summary
Sending to default printerSe a entrada for inventory, a saída deve ser:
Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse managerObserve como ambos os relatórios seguem exatamente a mesma estrutura de algoritmo (coletar, formatar, gerar), mas a implementação de cada etapa é personalizada. O SalesReport usa o comportamento de saída padrão, enquanto o InventoryReport o sobrescreve - demonstrando como o padrão Template Method permite controlar quais etapas são obrigatórias para sobrescrever e quais podem ser opcionalmente personalizadas!
Folha de consulta
O padrão Template Method 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 contém um "método template" que chama uma sequência de etapas. Algumas etapas são abstratas (devem ser implementadas pelas subclasses), enquanto outras podem ser virtuais (opcionais para sobrescrever):
public abstract class DataProcessor
{
// Método template - define a estrutura do algoritmo
public void Process()
{
ReadData();
ProcessData();
SaveData();
}
protected abstract void ReadData();
protected abstract void ProcessData();
protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}As subclasses fornecem suas próprias implementações enquanto a classe base impõe a ordem das operações:
public class CsvProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading CSV file");
protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}
public class JsonProcessor : DataProcessor
{
protected override void ReadData() => Console.WriteLine("Reading JSON file");
protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
protected override void SaveData() => Console.WriteLine("Saving to cloud");
}Uso:
DataProcessor csv = new CsvProcessor();
csv.Process();
// Reading CSV file
// Parsing CSV data
// Saving to default location
DataProcessor json = new JsonProcessor();
json.Process();
// Reading JSON file
// Parsing JSON data
// Saving to cloudO padrão Template Method é ideal quando várias classes compartilham a mesma estrutura de algoritmo, mas diferem em etapas específicas. Ele promove a reutilização de código ao colocar a lógica comum na classe base, permitindo flexibilidade por meio de métodos que podem ser sobrescritos.
Experimente você mesmo
using System;
using Reporting;
class Program
{
public static void Main(string[] args)
{
string reportType = Console.ReadLine();
// TODO: Criar o gerador de relatório apropriado com base no reportType
// Se reportType for "sales", crie um SalesReport
// Se reportType for "inventory", crie um InventoryReport
// Em seguida, chame o método Generate() no relatório
}
}
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 ExternosNamespaces e DiretivasIntrodução a Classes e ObjetosA Palavra-chave 'this'Métodos e ParâmetrosCampos vs PropriedadesConstrutoresInicializadores de ObjetosRecapitulação - Calculadora Simples4Herança
Sintaxe Básica de Herança (:)A Palavra-chave 'base'Palavras-chave Virtual e OverrideClasses SeladasA Classe Base 'object'Recapitulação - Hierarquia de Funcionários7Recursos Avançados
Sobrecarga de OperadoresIndexadores (this[])Sobrescrita de ToString()Métodos de ExtensãoRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoSingleton Thread-SafePadrão FactoryPadrão Observer (Eventos)Padrão Strategy2Propriedades e Membros Estáticos
Propriedades AutoimplementadasPropriedades de Apenas Leitura/EscritaCampos e Métodos EstáticosClasses EstáticasMembros com Corpo de Expressão5Polimorfismo e Interfaces
Polimorfismo: Compilação vs ExecuçãoInterface vs Classe AbstrataMúltiplas InterfacesInterfaces ExplícitasUpcasting e DowncastingRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição sobre HerançaGenerics (Classes e Métodos)Delegates e EventosAtributos e ReflectionIDisposable e a Instrução usingFundamentos de Injeção de Dependência11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Arquitetura de Classes
Dados de Instância vs EstáticosPalavras-chave 'readonly' e 'const'Campos de SuporteRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Modificadores de AcessoPropriedades para EncapsulamentoImplementação de Ocultação de DadosPadrões de ImutabilidadeRecapitulação - Registros de Estudantes9Argumentos Variáveis
A Palavra-chave 'params'Parâmetros OpcionaisArgumentos NomeadosSobrecarga de Métodos