No desenvolvimento de sistemas complexos, frequentemente nos deparamos com processos que seguem um roteiro fixo, mas com detalhes que mudam (como importação de arquivos), ou situações onde precisamos adicionar operações a uma estrutura de objetos sem modificá-la. Além disso, há o desafio de processar requisições que podem ser resolvidas por diferentes instâncias em uma corrente.
Neste artigo, veremos como o Delphi 13 utiliza esses padrões para criar códigos altamente extensíveis e com responsabilidades claramente definidas.
1. Template Method: Definindo o Esqueleto do Algoritmo
No desenvolvimento de sistemas corporativos, é comum encontrarmos processos que seguem uma sequência idêntica de passos, mas cujos detalhes de implementação variam conforme o contexto. O erro clássico é copiar e colar a estrutura do algoritmo (como blocos try..finally, logs e transações) em múltiplas classes. O padrão Template Method resolve isso ao inverter o controle: a classe base dita o ritmo, e as subclasses preenchem as lacunas.
O Template Method define o esqueleto de um algoritmo em uma operação, adiando alguns passos para as subclasses. Ele permite que as subclasses redefinam certos passos de um algoritmo sem mudar a estrutura do mesmo.
O Problema: Algoritmos “Copiados” e Falhas de Integridade
Imagine diferentes processos de exportação de dados (para Excel, PDF ou API). Todos precisam:
- Iniciar a conexão com a fonte de dados.
- Validar permissões do usuário.
- Processar a conversão específica.
- Registrar o log de sucesso ou erro.
- Encerrar a conexão.
- Sem Template Method: Você repete o
try..finallye a lógica de abertura em todas as classes. - O Risco: Se você implementar isso em classes separadas sem o Template Method, corre o risco de um desenvolvedor esquecer o log em uma delas ou não fechar a conexão no
finallyde outra. - Impacto no Delphi 13: O código torna-se redundante, difícil de auditar e propenso a vazamentos de recursos (resource leaks).
A Solução: Inversão de Controle e Métodos Gancho (Hooks)
O padrão propõe que o método principal (o Template) seja implementado na classe base e marcado como final (ou simplesmente não virtual), garantindo que a sequência de execução nunca seja alterada. Os detalhes variáveis são expostos através de métodos abstract ou virtual.
Por que isso revoluciona sua arquitetura no Delphi 13?
- Reutilização de Código de Infraestrutura: Toda a lógica de “cerimônia” (abrir/fechar arquivos, transações de banco) fica em um só lugar.
- Segurança de Execução: A classe base garante que o método de limpeza (
finally) será chamado, independentemente do que a subclasse faça no passo de processamento. - Uso de Hooks: No Delphi 13, você pode definir métodos virtuais vazios chamados Hooks. Eles permitem que as subclasses “entrem” no algoritmo em pontos específicos apenas se necessário, sem a obrigatoriedade de implementar todos os métodos (como ocorre com o
abstract).
Ao aplicar o Template Method, você cria um framework interno onde adicionar uma nova funcionalidade (como um novo formato de importação) resume-se a implementar apenas a lógica de extração, enquanto o Delphi 13 cuida de toda a segurança e fluxo operacional de forma transparente. A
classe base define o método principal (o template) e deixa métodos abstratos ou virtuais (hooks) para que as subclasses implementem apenas o processamento específico.
A Transição Técnica: No Delphi 13, utilizamos métodos protected para os passos do algoritmo, garantindo que o cliente chame apenas o método public que coordena a execução, mantendo a integridade do fluxo.
2. Chain of Responsibility: A Corrente de Processamento
O padrão Chain of Responsibility evita o acoplamento do remetente de uma solicitação ao seu receptor, ao dar a mais de um objeto a oportunidade de tratar a solicitação. Ele encadeia os objetos receptores e passa a solicitação ao longo da corrente até que um objeto a trate.
Implementação Técnica: O Fim dos “Nested Ifs”
Sistemas de aprovação de crédito ou triagem de suporte são exemplos perfeitos. Em vez de um grande bloco de decisão, cada “elo” da corrente decide se processa a requisição ou a passa para o próximo.
unit Regys.Patterns.ChainOfResponsibility;
interface
type
TRequisicao = record
Valor: Currency;
end;
IHandler = interface
['{E1D2C3B4-A5F6-4789-B0C1-D2E3F4A5B6C7}']
procedure SetNext(const ANext: IHandler);
procedure Processar(const AReq: TRequisicao);
end;
TBaseHandler = class(TInterfacedObject, IHandler)
protected
FNext: IHandler;
public
procedure SetNext(const ANext: IHandler);
procedure Processar(const AReq: TRequisicao); virtual;
end;
implementation
{ TBaseHandler }
procedure TBaseHandler.SetNext(const ANext: IHandler);
begin
FNext := ANext;
end;
procedure TBaseHandler.Processar(const AReq: TRequisicao);
begin
if Assigned(FNext) then
FNext.Processar(AReq);
end;
end.
3. Aplicação no Dia a Dia: Fluxos de Aprovação e Extensibilidade de Dados
No quotidiano de um arquiteto Delphi 13, o Chain of Responsibility e o Visitor permitem que o sistema cresça em funcionalidades sem que as classes core se tornem monstruosas ou impossíveis de testar.
A. Chain of Responsibility: O Fim dos Validadores Gigantescos
Um dos cenários mais comuns em ERPs é a validação de regras de negócio complexas (ex: “Pode vender para este cliente?”).
- Cenário de Caos: Um método
ValidarVendacom 500 linhas, verificando limite de crédito, estoque, bloqueios manuais, restrições fiscais e promoções. - A Solução com Chain: Cada regra torna-se um “elo” na corrente (ex:
TValidadorCredito,TValidadorEstoque). O pedido passa por cada elo. Se um elo falha, ele interrompe a corrente e retorna o erro. - Vantagem no Delphi 13: Você pode reordenar as validações, adicionar novas ou remover existentes apenas alterando a configuração da corrente, sem tocar em uma linha de código da regra de negócio de venda.
B. Visitor: Adicionando Operações a Hierarquias Complexas (Composite)
O Visitor é o parceiro ideal do padrão Composite (visto no Artigo 08). Ele resolve o dilema de: “Como eu adiciono exportação para JSON e Excel na minha árvore de produtos sem alterar todas as classes da hierarquia?”.
- Uso Prático: Em vez de colocar métodos de exportação dentro de cada classe de produto ou kit, você cria um
TExportVisitor. - A Mágica do Double Dispatch: Cada classe na sua hierarquia aceita o visitante (
Accept(Visitor)). O visitante então sabe exatamente como “visitar” um Produto Simples ou um Kit, extraindo os dados necessários. - Resultado: Suas classes de domínio permanecem limpas e focadas em dados, enquanto os algoritmos de exportação, auditoria ou cálculo ficam isolados em seus próprios visitantes.
C. Chain para Middleware e Triagem de Requisições
Em sistemas que utilizam arquitetura multi-tier ou micro-serviços com Delphi, o Chain of Responsibility atua como um Middleware. Antes de uma requisição chegar ao banco de dados, ela passa por uma corrente de: Logger -> Autenticador -> ValidadorSchema -> Cache. Isso garante que o processamento pesado só ocorra se a requisição for legítima e necessária.
D. Visitor para Auditoria e Transformação de Dados
Utilize o Visitor para realizar tarefas de auditoria em grafos de objetos complexos (como um Pedido com seus Itens, Parcelas e Impostos). O Visitor percorre toda a estrutura e gera um relatório de mudanças ou uma representação serializada, permitindo que você mude o formato de saída apenas criando um novo visitante, sem nunca modificar o core do seu modelo de dados.
4. Nuances Técnicas: Performance, Memória e a “Magia” do Double Dispatch
Implementar Template Method, Chain of Responsibility e Visitor no Delphi 13 exige mais do que conhecimento teórico; exige entender como o compilador e o gerenciador de memória lidam com o encadeamento e a profundidade das chamadas.
A. Template Method e a Segurança de Recursos
Ao definir o esqueleto de um algoritmo, a responsabilidade de gerenciar recursos (como TStringStream ou TFDQuery) deve ser da classe base.
- Prática Sênior: Utilize o bloco
try..finallyno método Template. Isso garante que, mesmo que o método implementado pela subclasse falhe e levante uma exceção, o recurso será liberado. As subclasses no Delphi 13 devem focar apenas na transformação dos dados, nunca na gestão do ciclo de vida da infraestrutura que o Template provê.
B. Chain of Responsibility: O Custo do Encadeamento
Cada elo na corrente é uma instância de classe. Se você tiver uma corrente com 50 validadores:
- Memory Management: Utilize interfaces (
IHandler). Ao destruir a referência do primeiro elo, a contagem de referência cairá em cascata por toda a corrente, liberando a memória de forma atômica. - Early Exit: Para performance, ordene sua corrente colocando os elos que falham mais rápido (ou que resolvem a maioria dos casos simples) no início. Isso evita que o Delphi 13 processe lógicas complexas e alocações desnecessárias no final da corrente.
C. Visitor e a Performance do Double Dispatch
O padrão Visitor utiliza o Double Dispatch (o elemento aceita o visitante e o visitante visita o elemento). Isso gera duas chamadas de métodos virtuais por operação.
- O Mito da Lentidão: Embora sejam duas indireções, o custo para o processador moderno é desprezível.
- O Perigo da Recursividade: Se o Visitor estiver percorrendo um Composite (Artigo 08) muito profundo, fique atento ao uso da pilha (Stack). No Delphi 13, para estruturas gigantescas, prefira usar um Visitor que utilize uma pilha interna (
TStack<T>) em vez de recursão pura para evitar Stack Overflow.
D. Métodos Gancho (Hooks) vs. Abstract
No Delphi 13, prefira o uso de métodos virtuais com implementação vazia (Hooks) no Template Method. Isso dá flexibilidade total para quem herda a classe. Se você usar abstract, forçará a implementação de todos os passos, o que pode gerar códigos vazios e inúteis nas subclasses, poluindo o projeto e dificultando a leitura.
Referências
FLICK, Stefan. Design Patterns with Delphi: Build enterprise-grade applications with modern Delphi and the right design patterns. 1. ed. Birmingham: Packt Publishing, 2024.
GAMMA, Erich; HELM, Richard; JOHNSON, Ralph; VLISSIDES, John. Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos. 1. ed. Porto Alegre: Bookman, 2000.
NOGUEIRA, Rodrigo. Delphi e Clean Architecture: Princípios e práticas para software escalável. 2. ed. São Paulo: Editora Engenharia de Software, 2025.
TEIXEIRA, Marcello. Delphi High Performance: Build fast Delphi applications using concurrency, parallel programming and memory management. 1. ed. Birmingham: Packt Publishing, 2018.
Descubra mais sobre Régys Borges da Silveira
Assine para receber nossas notícias mais recentes por e-mail.
Dê-nos sua opinião, seu comentário ajuda o site a crescer e melhorar a qualidade dos artigos.