Tecnologia além do código.
Régys Borges da Silveira
← Voltar para explorar os artigos

Design Patterns em Delphi 13: Composite e Bridge – Hierarquias e Abstrações

Neste artigo 16 tópicos

Como desenvolvedores Delphi, frequentemente lidamos com dois desafios arquiteturais: representar estruturas de árvore (como menus, organogramas ou composições de produtos) e evitar a explosão de classes quando uma funcionalidade precisa rodar em múltiplas plataformas ou bancos de dados.

Neste artigo, veremos como o Composite nos permite tratar objetos individuais e composições de forma uniforme, e como o Bridge desata o nó entre o “o que o objeto faz” e “como ele é implementado” no Delphi 13.

1. Composite: A Unificação de Partes e Todo

O padrão Composite é utilizado para compor objetos em estruturas de árvore. Ele permite que os clientes tratem objetos individuais e composições de objetos de maneira idêntica.

O Problema: Tratamento Diferenciado para Grupos e Itens

Imagine um sistema de vendas onde um “Item” pode ser um produto simples ou um “Kit” contendo vários produtos.

  • Modo Antigo: Você precisa de ifs constantes para verificar se está lidando com um TProduto ou um TKit. O código de cálculo de preço torna-se complexo e difícil de manter.
  • Modo Moderno (Delphi 13): Tanto o produto quanto o kit implementam a mesma interface IComponente. O Kit armazena uma lista de IComponente, permitindo chamadas recursivas transparentes.

A Transição Técnica: O Composite elimina a necessidade de o cliente conhecer a estrutura interna da árvore. Se você chamar GetPreco, o componente individual retorna seu valor, enquanto o composto percorre seus filhos e soma os resultados, tudo de forma polimórfica.

2. Bridge: Separando a Abstração da Implementação

O padrão Bridge foca na “desconexão”. Ele separa uma abstração de sua implementação, permitindo que ambas variem independentemente. No Delphi 13, isso é essencial para sistemas que suportam múltiplos drivers de banco de dados ou engines de renderização.

Implementação Técnica: Evitando a Explosão de Subclasses

Se você tem uma classe TRelatorio e precisa de versões PDF e HTML para Windows e Linux, a herança tradicional exigiria 4 subclasses. Com o Bridge, você tem a hierarquia de Relatórios (Abstração) e a hierarquia de Renderizadores (Implementação).

unit Regys.Patterns.Bridge;

interface

type
  // 1. A Implementação (O "Como")
  IRenderizador = interface
    ['{C1D2E3B4-A5F6-4789-B0C1-D2E3F4A5B6C7}']
    procedure RenderizarTexto(const ATexto: string);
  end;

  // 2. A Abstração (O "O Que")
  TRelatorio = class
  protected
    FRender: IRenderizador;
  public
    constructor Create(const ARender: IRenderizador);
    procedure Gerar; virtual; abstract;
  end;

  // 3. Abstração Refinada
  TRelatorioVendas = class(TRelatorio)
  public
    procedure Gerar; override;
  end;

  // 4. Implementador Concreto
  TRenderPDF = class(TInterfacedObject, IRenderizador)
  public
    procedure RenderizarTexto(const ATexto: string);
  end;

implementation

{ TRelatorioVendas }
constructor TRelatorio.Create(const ARender: IRenderizador);
begin
  FRender := ARender;
end;

procedure TRelatorioVendas.Gerar;
begin
  FRender.RenderizarTexto('Relatório de Vendas Gerado');
end;

{ TRenderPDF }
procedure TRenderPDF.RenderizarTexto(const ATexto: string);
begin
  // Lógica específica para gerar PDF no Delphi 13
end;

end.

3. Aplicação no Dia a Dia: Flexibilidade e Estruturas Recursivas

No cotidiano de um arquiteto Delphi 13, o Composite e o Bridge são frequentemente utilizados em conjunto para resolver problemas de escala e multiplataforma. Enquanto um organiza a estrutura interna dos dados, o outro protege o sistema contra mudanças nas APIs externas ou de hardware.

A. Composite: Menus, Permissões e Árvores de Produtos

O uso mais prático do Composite no Delphi ocorre quando precisamos gerenciar estruturas onde um “item” pode ser, na verdade, um “grupo de itens”.

  • Cenário de Uso (ERPs): Imagine um sistema de permissões de acesso. Você tem “Permissões Simples” (ex: Ler, Escrever) e “Grupos de Permissões” (ex: Gerente, Operador).
  • Transição Clean: Ao tratar ambos como IPermissao, o seu método Usuario.TemAcesso(IPermissao) funciona de forma recursiva. Se o usuário tentar acessar uma permissão que é um Grupo, o Composite percorre todos os filhos automaticamente.
  • Resultado: Você elimina loops for e verificações de tipo (is / as) espalhados pelo código, centralizando a lógica de travessia na classe composta.

B. Bridge: O Escudo contra a Explosão de Subclasses Multiplataforma

O Bridge é o padrão “salva-vidas” para desenvolvedores que precisam manter um core único para Windows (VCL) e Android/iOS (FMX), ou para sistemas que suportam múltiplos motores de banco de dados.

  • Exemplo Real: Suponha que você tenha uma classe de TEmissorBoleto. Se você precisar emitir boletos via API REST e também via componentes locais (como FastReport), a herança criaria um nó górdio.
  • A Solução com Bridge: Você separa a Abstração (TBoleto) da Implementação (IProvedorEmissao).
  • Vantagem: Você pode adicionar um novo banco ou um novo layout de impressão apenas criando uma nova implementação da interface, sem nunca tocar na regra de negócio que calcula juros e multas.

C. Composição em Engines de Relatórios e UI

No Delphi 13, ao construir componentes visuais complexos ou geradores de documentos, o Composite permite que você trate cada “quadro”, “linha” ou “campo” como um nó de uma árvore. Isso facilita a implementação de funcionalidades como “Esconder Grupo” ou “Calcular Soma do Grupo”, pois a chamada é propagada naturalmente pela árvore de objetos, respeitando a hierarquia visual.

D. Bridge para Persistência e Drivers (FireDAC/REST)

Muitas software houses estão migrando de Client/Server para Multi-tier. O Bridge permite que sua aplicação utilize um TDataBridge que pode ser configurado para usar um TLocalDriver (FireDAC direto no banco) ou um TRemoteDriver (chamadas REST/JSON), permitindo que o mesmo executável funcione em cenários de rede local ou nuvem apenas trocando a implementação injetada.

4. Nuances Técnicas: Performance e Gerenciamento de Árvores no Delphi 13

Implementar os padrões Composite e Bridge no Delphi 13 exige mais do que apenas criar classes e interfaces; exige um entendimento de como o compilador gerencia recursividade e instâncias automáticas.

A. Recursividade e a Pilha (Stack Overflow) no Composite

O padrão Composite baseia-se fortemente em chamadas recursivas para percorrer árvores. No Delphi 13, embora o limite da stack seja generoso, árvores extremamente profundas (milhares de níveis) podem causar um Stack Overflow.

  • Técnica Sênior: Se a sua estrutura for muito profunda, considere implementar a travessia usando um padrão Iterator ou uma pilha manual (TStack<T>) para transformar a recursão em uma iteração, protegendo a estabilidade da aplicação.

B. Gestão de Memória em Estruturas de Árvore

O maior desafio do Composite é garantir que, ao destruir um “Nó Pai”, todos os “Filhos” sejam liberados.

  • Solução Moderna: No Delphi 13, utilize TList<IInterface> ou TInterfaceList para armazenar os filhos. Graças à contagem de referência, quando o pai é liberado e a lista interna é destruída, a referência dos filhos cai para zero e eles são limpos automaticamente.
  • Atenção: Evite referências circulares (um filho que aponta para o pai). Se for necessário que o filho conheça o pai, use o atributo [Weak] no campo que armazena o pai para evitar vazamentos de memória (Memory Leaks).

C. O Custo da Indireção no Bridge

O Bridge introduz uma camada extra de indireção (Abstração -> Implementação). No Delphi 13, isso significa uma chamada adicional através de uma interface ou ponteiro de método.

  • Impacto Real: Em 99% das aplicações empresariais, esse custo é irrelevante. No entanto, em loops críticos de alta performance (como processamento de milhares de pixels ou cálculos matemáticos intensos), essa indireção pode ser notada.
  • Otimização: Avalie se a implementação pode ser injetada uma única vez no início do processo para evitar resoluções constantes de interface dentro de loops pesados.

D. Injeção de Dependência no Bridge

Para que o Bridge seja verdadeiramente eficaz no Delphi 13, a Abstração não deve instanciar a Implementação concreta.

  • Prática Recomendada: Utilize Injeção de Dependência via construtor. Isso permite que você troque o driver de banco ou o engine de relatórios em tempo de execução sem alterar a classe de Abstração, facilitando testes de unidade com Mocks.

E. Resumo

  • Recursividade no Composite: No Delphi 13, certifique-se de que a recursividade do Composite tenha um ponto de parada para evitar Stack Overflow em árvores excessivamente profundas.
  • Memória em Estruturas Composite: Como o Composite lida com coleções de objetos, o uso de TInterfaceList ou TList<IInterface> é altamente recomendado. Isso garante que, ao destruir o “pai”, todos os “filhos” sejam liberados corretamente via contagem de referência.
  • Desacoplamento no Bridge: O segredo do Bridge no Delphi 13 é que a Abstração contém uma referência para a Interface da Implementação (Composição). Isso permite que você mude o comportamento do objeto em tempo de execução apenas trocando o objeto de implementação injetado.

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.

Compartilhar por e-mail

0 comentário(s)

Dê-nos sua opinião, seu comentário ajuda o site a crescer e melhorar a qualidade dos artigos.

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.

Um próximo passo para cada interesse.

Continue estudando com os livros, acompanhe as videoaulas ou consulte as soluções para o seu projeto.

Descubra mais sobre Régys Borges da Silveira

Assine agora mesmo para continuar lendo e ter acesso ao arquivo completo.

Continuar lendo