O padrão Template Method é classificado como um padrão de projeto comportamental. Sua principal função é estabelecer a estrutura fundamental de um algoritmo em uma superclasse, delegando a execução de etapas específicas para suas subclasses. Essa abordagem permite que as classes derivadas modifiquem partes do comportamento sem alterar a arquitetura geral do algoritmo.
Uma desvantagem notável dessa técnica é a potencial proliferação de classes no sistema, uma vez que cada variação do algoritmo exige a criação de uma nova subclasse. No entanto, esse custo é compensado por uma distribuição de responsabilidades muito mais clara, aderidno ao princípio da responsabilidade única e aumentando significativamente a coesão do código.
Vantagens Principais
Atua como uma técnica fundamental para o reuso de código, centralizando a lógica invariável e evitando duplicações em nível de arquitetura.
Cenários de Aplicação
- Quando é necessário consolidar a parte imutável de um algoritmo em um único local, permitindo que as subclasses implementem apenas os comportamentos voláteis.
- Sempre que houver comportamentos idênticos espalhados por diversas subclasses. O padrão permite extrair essa lógica comum para uma classe base, mitigando a repetição de código através da generalização.
Exemplo Prático em C#
Abaixo, demonstramos a aplicação do padrão utilizando um contexto de processamento de arquivos de dados. A estrutura foi redesenhada para ilustrar como a classe base orquestra o fluxo de execução, enquanto as implementações concretas ditarão como a extração de dados deve ocorrer.
public abstract class DataFile
{
/// <summary>
/// Salva os dados processados.
/// </summary>
public void Save()
{
Console.WriteLine("Persistindo dados no armazenamento.");
}
/// <summary>
/// Prepara o arquivo para leitura.
/// </summary>
public void Open(string path)
{
Console.WriteLine($"Inicializando leitura do arquivo: {path}");
}
/// <summary>
/// Libera os recursos utilizados.
/// </summary>
public void Close()
{
Console.WriteLine("Encerrando conexão com o arquivo.");
}
// Método abstrato que força a implementação da lógica de extração pelas subclasses
public abstract void ExtractData(string path);
}
public abstract class FileProcessor
{
private readonly IList<DataFile> _files = new List<DataFile>();
/// <summary>
/// Hook method: verifica se o arquivo pode ser processado.
/// Pode ser sobrescrito pelas subclasses se necessário.
/// </summary>
protected virtual bool IsProcessable(string path)
{
return !string.IsNullOrWhiteSpace(path);
}
private void Register(DataFile file)
{
_files.Add(file);
Console.WriteLine("Arquivo incluído na fila de processamento.");
}
// Método abstrato (Factory Method) para instanciar o tipo correto de arquivo
protected abstract DataFile CreateDataFile();
/// <summary>
/// O Template Method que orquestra o esqueleto do algoritmo.
/// </summary>
public void Process(string path)
{
if (!IsProcessable(path))
{
Console.WriteLine("Caminho inválido. Operação abortada.");
return;
}
DataFile currentFile = CreateDataFile();
currentFile.Open(path);
currentFile.ExtractData(path);
Register(currentFile);
}
}