À medida que um projeto Delphi cresce, é natural que o número de classes, units e componentes aumente drasticamente. O problema surge quando a camada de interface (UI) ou outras partes do sistema precisam interagir com dezenas de classes apenas para realizar uma tarefa simples, como emitir uma nota fiscal ou processar um fechamento de caixa. Sem os padrões adequados, o seu código vira um emaranhado de dependências.
Neste artigo, vamos aprender como o Facade simplifica o caos e como o Proxy atua como um intermediário inteligente no Delphi 13.
1. Facade: Domando a Complexidade do Subsistema
O padrão Facade fornece uma interface unificada para um conjunto de interfaces em um subsistema. Ele define uma interface de nível mais alto que torna o subsistema mais fácil de usar.
O Problema: Acoplamento com Múltiplas Units
Imagine que para realizar uma venda, seu formulário precise instanciar: TEstoque, TFinanceiro, TNotaFiscal, TEmailService e TLog.
- Modo Antigo: O
OnClickdo botão tem 50 linhas apenas configurando esses objetos. - Modo Clean Code (Delphi 13): Você cria uma classe
TVendaFacade. O formulário chama apenasVendaFacade.FinalizarVenda(Dados).
A Transição Técnica: O Facade não “esconde” as classes do subsistema de forma que elas fiquem inacessíveis, mas oferece um atalho para as tarefas mais comuns. No Delphi 13, isso reduz drasticamente o uses das suas Units de interface.
2. Proxy: O Intermediário Inteligente
O padrão Proxy fornece um substituto ou um marcador de lugar para outro objeto para controlar o acesso a ele. No Delphi 13, ele é vital para Lazy Loading, controle de permissões e log de auditoria.
Implementação Técnica: Proxy de Proteção e Virtual Proxy
Um uso clássico no dia a dia é o carregamento de imagens pesadas ou relatórios que consomem muita memória.
unit Regys.Patterns.Proxy;
interface
type
// Interface comum para o Proxy e o Objeto Real
IServicoRelatorio = interface
['{F1E2D3C4-B5A6-4789-B0C1-D2E3F4A5B6C7}']
procedure GerarRelatorio;
end;
// O Objeto Real (Pesado e Caro)
TRelatorioPesado = class(TInterfacedObject, IServicoRelatorio)
public
constructor Create;
procedure GerarRelatorio;
end;
// O Proxy (Leve, controla o acesso)
TRelatorioProxy = class(TInterfacedObject, IServicoRelatorio)
private
FRelatorioReal: IServicoRelatorio;
FUsuarioTemPermissao: Boolean;
public
constructor Create(const ATemPermissao: Boolean);
procedure GerarRelatorio;
end;
implementation
{ TRelatorioPesado }
constructor TRelatorioPesado.Create;
begin
// Simula um carregamento de 5 segundos de dados do banco
Sleep(5000);
end;
procedure TRelatorioPesado.GerarRelatorio;
begin
Writeln('Relatório gerado com sucesso.');
end;
{ TRelatorioProxy }
constructor TRelatorioProxy.Create(const ATemPermissao: Boolean);
begin
FUsuarioTemPermissao := ATemPermissao;
end;
procedure TRelatorioProxy.GerarRelatorio;
begin
if not FUsuarioTemPermissao then
raise Exception.Create('Acesso negado!');
// Lazy Initialization (Virtual Proxy): Só cria o objeto caro se necessário
if not Assigned(FRelatorioReal) then
FRelatorioReal := TRelatorioPesado.Create;
FRelatorioReal.GerarRelatorio;
end;
end.
3. Aplicação no Dia a Dia: Blindando o Core do Sistema
No cotidiano de um desenvolvedor Delphi 13, a aplicação estratégica destes padrões separa sistemas frágeis de arquiteturas resilientes. Enquanto o Facade simplifica a “conversa” entre camadas, o Proxy garante que essa conversa só aconteça sob as condições certas.
A. Facade como Orquestrador de Integrações (Fiscal e Bancária)
Um dos cenários mais comuns no ecossistema Delphi é o uso de componentes gigantescos, como o ACBr ou bibliotecas de boletos.
- Cenário de Uso: Para emitir uma NF-e, você precisa configurar emitente, destinatário, itens, impostos, certificados e protocolos de envio.
- Transição Clean: Em vez de poluir seu
TServiceouTFormcom centenas de linhas de configuração de componentes, você cria umTFiscalFacade. - Resultado: Seu sistema chama apenas
FiscalFacade.Emitir(VendaId). Se amanhã você precisar trocar o componente de emissão ou migrar para uma API em nuvem, o impacto no seu código de negócio é zero. O Facade isola a volatilidade das ferramentas externas.
B. Proxy de Proteção: Segurança e Regras de Acesso
Em sistemas ERP complexos, nem todo usuário pode executar todas as operações, mas espalhar if Usuario.Perfil = 'Gerente' por todo o código é um erro clássico de manutenção.
- Uso Prático: Implementamos um Proxy que envolve a classe de negócio. Antes de delegar a chamada para o objeto real, o Proxy consulta o serviço de permissões.
- Vantagem: A classe real foca apenas na regra de negócio (SRP), enquanto o Proxy foca na segurança. Isso facilita auditorias e mudanças nas políticas de acesso sem tocar no código core.
C. Virtual Proxy para Performance em Grids e Dashboards
O Delphi 13 é excelente para lidar com grandes volumes de dados, mas carregar objetos pesados (como fotos de produtos ou históricos de transações) para mil registros de uma vez causará lentidão e consumo excessivo de memória.
- Implementação no Delphi 13: Utilizamos um Virtual Proxy dentro de um
TObjectList. O objeto na lista é o Proxy; ele é leve e contém apenas o ID. Quando a UI solicita o campoFotoouHistorico, o Proxy verifica se o objeto real já foi carregado. Caso contrário, ele busca no banco (Lazy Loading) no exato momento da demanda.
D. Proxy de Log e Auditoria (Observabilidade)
Com o aumento da necessidade de conformidade (LGPD), rastrear quem alterou o quê é vital. Um Proxy de Auditoria pode interceptar chamadas aos métodos de persistência, registrando o estado anterior e o novo estado do objeto de forma automática e transparente para o restante do sistema.
4. Nuances Técnicas: Memória e Transparência no Delphi 13
Implementar Facades e Proxies no Delphi 13 não se resume a criar classes intermediárias; trata-se de gerenciar o ciclo de vida dos objetos de forma que o padrão não se torne um fardo para o hardware.
A. Ownership e Ciclo de Vida no Facade
O Facade, por definição, orquestra múltiplos subsistemas. No Delphi 13, a decisão crítica é: o Facade é o “dono” (owner) dos objetos que ele utiliza?
- Recomendação: Se o Facade instancia classes concretas (como um
TFDConnectionou umTACBrPosPrinter), ele deve obrigatoriamente implementar odestructor Destroypara liberar esses recursos. - Abordagem Moderna: Utilize o Facade retornando Interfaces. Isso permite que o Facade gerencie a criação, mas o Delphi gerencie a destruição via contagem de referência, simplificando o uso por parte do desenvolvedor da UI.
B. Transparência do Proxy e o Custo da Indireção
Para que um Proxy seja eficaz, ele deve ser indistinguível do objeto real. No Delphi 13, isso é alcançado através de Interfaces.
- Performance: Muitos temem que a camada extra do Proxy degrade a performance. Contudo, o custo de uma chamada de método via Interface é insignificante (nanosegundos). O verdadeiro ganho de performance vem do Virtual Proxy: ao evitar a criação de um objeto de 10MB que o usuário nunca chegaria a abrir, você economiza muito mais recursos do que o custo da indireção.
C. Gerenciamento de Memória em Lazy Loading (Proxy)
O maior risco em um Proxy de carregamento tardio (Lazy Loading) no Delphi 13 é o vazamento de memória se o objeto real for criado mas nunca liberado.
- Técnica Sênior: Se o seu Proxy for um
TInterfacedObject, a referência ao objeto real deve ser armazenada em um campo privado que implemente a mesma interface. Dessa forma, quando o Proxy morre, a referência do objeto real cai para zero e ele também é liberado. - Atenção: Se o objeto real for uma classe pura (
TObject), o Proxy precisa dar oFreenele manualmente no seu próprioDestroy.
D. Concorrência e Thread Safety no Delphi 13
Em aplicações multithread (como servidores REST), um Proxy que faz Lazy Loading pode sofrer de Race Conditions.
- Solução: No Delphi 13, utilize o
TMonitor.Enter(Self)ouTCriticalSectiondentro do Proxy para garantir que, se duas threads tentarem acessar o recurso pesado simultaneamente, o objeto real seja instanciado apenas uma vez com segurança.
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.