Tecnologia além do código.
Régys Borges da Silveira

Design Patterns em Delphi 13: Iterator, Mediator e Memento – Navegação e Memória

Neste artigo 16 tópicos

À medida que os sistemas se tornam mais complexos, dois problemas surgem: como percorrer coleções de objetos sem expor sua estrutura interna e como evitar que dezenas de classes fiquem acopladas entre si (o famoso “código espaguete”). Além disso, surge a necessidade de salvar o estado de um objeto para restauração futura.

Neste artigo, veremos como o Delphi 13 resolve esses dilemas com padrões que trazem ordem à comunicação e persistência temporária de dados.

1. Iterator: Navegação Padronizada e Abstrata

No desenvolvimento Delphi tradicional, é comum percorrermos listas usando índices (for i := 0 to Count - 1). No entanto, essa abordagem amarra o seu código a uma implementação específica: a de uma lista indexada. O padrão Iterator quebra esse vínculo, permitindo percorrer qualquer coleção de objetos sem expor como eles estão armazenados. O padrão Iterator fornece uma maneira de acessar sequencialmente os elementos de um objeto agregado sem expor sua representação subjacente.

O Problema: Acoplamento e Rigidez de Travessia

Quando você escreve um algoritmo que depende de um índice, você assume que a estrutura de dados permite acesso aleatório rápido.

  • O Risco: Se amanhã você precisar trocar um TObjectList por um TDictionary ou uma estrutura de árvore (como visto no padrão Composite), todos os seus laços de repetição precisarão ser reescritos.
  • Impacto no Delphi 13: O código torna-se difícil de refatorar e propenso a erros de “index out of bounds” quando a lógica de filtragem ou ordenação muda.

A Solução: Navegação Polimórfica com IEnumerable

O padrão Iterator propõe o uso de um objeto separado (o Iterador) que conhece a mecânica de navegação da coleção. No Delphi 13, isso é implementado de forma elegante através da interface IEnumerator<T>.

Por que isso transforma sua arquitetura?

  1. Abstração Total: O seu código de negócio pede um enumerador e consome os dados. Ele não sabe se os dados vêm de um array em memória, de um arquivo TXT ou de uma query SQL paginada.
  2. Suporte Nativo ao for-in: Ao implementar o padrão Iterator (via método GetEnumerator), sua classe customizada ganha suporte automático ao laço for-in, tornando o código muito mais limpo e legível.
  3. Iteradores Especializados: Você pode criar múltiplos iteradores para a mesma coleção. Por exemplo, um TOrdemCronologicaIterator e um TOrdemPrioridadeIterator, permitindo mudar a forma de navegar nos dados apenas trocando o objeto iterador, sem alterar a coleção original.

No Delphi 13, a combinação de Generics com o Iterator permite criar algoritmos de processamento de listas que são completamente independentes do tipo de dado e da estrutura de armazenamento, elevando o nível de reuso do seu framework interno.

A Transição Técnica: No Delphi 13, implementar o GetEnumerator permite que suas classes customizadas funcionem com o laço for-in, escondendo a complexidade da iteração (como pular registros inativos ou filtrar dados em tempo real).

2. Mediator: O Controlador de Tráfego Aéreo

O padrão Mediator define um objeto que encapsula como um conjunto de objetos interage. Ele promove o desacoplamento ao impedir que os objetos se refiram uns aos outros explicitamente.

Implementação Técnica: Reduzindo o Caos em Formulários Complexos

Imagine um formulário com 20 campos, onde o comportamento do Botão Salvar depende do CheckBox A, que limpa o Edit B, que habilita o Combo C.

  • Sem Mediator: Cada componente conhece os outros 19. O código fica impossível de manter.
  • Com Mediator: Todos os componentes falam apenas com o Mediator. Ele centraliza a lógica de interação.
unit Regys.Patterns.Mediator;

interface

type
  IMediator = interface;

  // Colega (Componente que interage)
  TBaseComponent = class
  protected
    FMediator: IMediator;
  public
    constructor Create(AMediator: IMediator);
  end;

  // A Interface do Mediador
  IMediator = interface
    procedure Notificar(Sender: TBaseComponent; Evento: string);
  end;

  // Mediador Concreto
  TFormMediator = class(TInterfacedObject, IMediator)
  public
    procedure Notificar(Sender: TBaseComponent; Evento: string);
  end;

implementation

{ TFormMediator }
procedure TFormMediator.Notificar(Sender: TBaseComponent; Evento: string);
begin
  if Evento = 'CheckAlterado' then
  begin
    // Lógica centralizada: se check mudou, desabilita outros campos
  end;
end;

end.

3. Memento: A Máquina do Tempo dos Objetos

No quotidiano de um arquiteto Delphi 13, o Mediator e o Memento são as ferramentas que impedem que um formulário se transforme num emaranhado de dependências cruzadas e garantem que o utilizador possa cancelar operações complexas com total segurança.

A. Mediator: O Fim do “Código Esparguete” em Formulários

Em sistemas ERP, é comum termos ecrãs de cadastro com dezenas de componentes que interagem entre si (ex: selecionar um tipo de pessoa habilita o campo CPF ou CNPJ, limpa a Inscrição Estadual e altera o Label da Foto).

  • Cenário de Caos: Sem o Mediator, cada componente tem código no seu evento OnChange que referencia diretamente outros cinco componentes. Se precisar de remover um campo, o sistema deixa de compilar em múltiplos pontos.
  • A Solução com Mediator: Todos os componentes notificam apenas o Mediator. Este objeto central contém a inteligência de negócio da interface.
  • Vantagem: O formulário torna-se puramente visual. A lógica de “quem habilita quem” fica isolada, facilitando a manutenção e permitindo que a mesma lógica seja reutilizada em diferentes versões do ecrã (VCL e FMX, por exemplo).

B. Memento: Snapshots de Segurança para Edição de Dados

O padrão Memento é a resposta elegante para o botão “Cancelar” em formulários complexos ou assistentes (Wizards).

  • Uso Prático: Antes de abrir o ecrã para edição, o objeto de negócio (ex: TCliente) gera um Memento (um snapshot do seu estado interno atual). Se o utilizador fizer alterações e decidir cancelar, o sistema simplesmente restaura o estado do objeto a partir do Memento.
  • Diferença para o Undo: Enquanto o Command (Artigo 10) guarda a ação para revertê-la, o Memento guarda o estado. É muito mais eficiente para restaurar um objeto completo após múltiplas alterações rápidas que não precisam de ser desfeitas uma a uma.

C. Mediator para Comunicação entre Frames e Micro-Forms

No Delphi 13, a modularização com TFrame é comum. O desafio é fazer com que o FrameA fale com o FrameB sem que um conheça a existência do outro. O Mediator atua como um barramento de eventos centralizado, onde os Frames se registam para enviar e receber mensagens, mantendo o desacoplamento total exigido por uma Clean Architecture.

D. Memento e Persistência Temporária

O Memento pode ser utilizado para implementar funções de “Auto-save” ou recuperação após falhas. Ao serializar o Memento (em JSON ou Stream) e guardá-lo num cache local, o sistema pode restaurar o trabalho do utilizador exatamente onde ele parou, mesmo que a aplicação tenha sido encerrada inesperadamente, proporcionando uma experiência de utilizador superior.

4. Nuances Técnicas: Performance e Encapsulamento no Delphi 13

Implementar os padrões Iterator, Mediator e Memento no Delphi 13 exige atenção especial ao ciclo de vida dos objetos e ao custo computacional de manter múltiplos estados na memória.

A. Performance de Iteração e o Custo do Enumerador

Ao implementar o padrão Iterator, o Delphi cria um objeto enumerador. Em loops críticos de alta performance:

  • Overhead: A criação de um objeto para cada for-in pode ter um custo pequeno, mas acumulativo. No Delphi 13, o compilador tenta otimizar enumeradores de arrays e listas genéricas, mas para coleções customizadas, certifique-se de que o seu GetEnumerator retorne uma instância de forma eficiente.
  • Tipagem: Utilize sempre Generics (IEnumerator<T>) para evitar o custo de typecasting (RTTI) durante a iteração, garantindo que o compilador possa otimizar o acesso aos dados.

B. Gestão de Memória no Mediator (Referências Circulares)

O Mediator é o centro de uma teia de comunicações. O risco aqui é a Referência Circular: o Mediador conhece os Colegas e os Colegas conhecem o Mediador.

  • Solução Técnica: No Delphi 13, utilize o atributo [Weak] ou IInterface com cuidado. Se todos forem TInterfacedObject, a referência mútua impedirá que a contagem de referência chegue a zero, causando um memory leak.
  • Prática Recomendada: O Mediador deve ser o dono dos colegas, ou os colegas devem ter uma referência fraca para o Mediador.

C. Memento: Custo de Memória e Deep Copy

O padrão Memento armazena o estado do objeto. Se o seu objeto for complexo (contendo outras listas ou objetos internos), você precisará decidir entre:

  1. Shallow Copy: Copia apenas os valores primitivos e ponteiros (rápido, mas perigoso se o objeto interno mudar).
  2. Deep Copy (Recomendado): Cria uma cópia completa de toda a árvore de objetos. No Delphi 13, isso pode ser feito via serialização JSON rápida ou Streams de memória.
  • Dica de Performance: Para objetos muito grandes, armazene no Memento apenas o “Delta” (o que mudou) em vez do estado completo, economizando memória RAM.

D. Notificações no Mediator e o Risco de Loop Infinito

Em implementações de Mediator, um evento pode gerar uma cadeia de notificações. Se não houver controle, o Componente A notifica o Mediator, que notifica o Componente B, que por sua vez notifica o Mediator novamente, gerando um Stack Overflow.

  • Proteção: Utilize flags de estado (ex: FProcessandoNotificacao: Boolean) dentro do Mediator para ignorar notificações recursivas enquanto uma lógica de atualização já estiver em curso.

E. Resumo

  • Iterator e Generics: O uso de System.Generics.Collections torna o Iterator extremamente performático no Delphi 13, permitindo iterações tipadas que evitam o custo de typecasting.
  • Mediator vs. Eventos: Enquanto o TNotifyEvent é útil para ações simples, o Mediator é superior para fluxos de trabalho, pois centraliza a lógica que estaria espalhada em dezenas de manipuladores de eventos.
  • Memento e Memória: Guardar snapshots de objetos grandes pode consumir muita memória. No Delphi 13, considere usar o padrão Memento apenas para os dados essenciais ou implemente um limite de estados salvos.

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