12 de fevereiro de 2011

Design Patterns com Delphi: Memento – Parte I

Num sistema computacional, são muitas as situações que podem exigir que tenhamos controle sobre o estado atual de um objeto para poder revertê-lo caso alguma alteração feita no estado desse objeto não deva ser levada adiante. O comando "desfazer" (undo), presente em muitos programas, é o exemplo mais comum, mas esse tipo de necessidade também pode ter outras aplicações: o tratamento de rollback (uma das características mais marcantes em sistemas de gerenciamento de banco de dados), em funções de preview (onde alterações podem ser aplicadas temporariamente para que se avalie o impacto que elas terão caso sejam efetivadas) e para trazer de volta o estado original de objetos quando uma situação de erro é encontrada durante uma atualização.

O Design Pattern comportamental Memento foi concebido justamente para ser aplicado nessas situações. A implementação proposta por ele respeita o encapsulamento do objeto envolvido enquanto proporciona-lhe a capacidade de salvar e exportar seu estado num determinado instante e de retornar a qualquer um dos estados salvos no momento em que isso for necessário.

A imagem abaixo é um diagrama UML retratando a relação típica entre as classes participantes da solução para o Memento. Aqui, a ideia é construir uma tela para realizar uma operação de crédito que terá que ser desfeita caso o limite de crédito seja atingido. Nesta condição, um estado previamente salvo pela rotina será restaurado.
Diagrama UML para o padrão Memento

O GoF classifica os participantes nesta solução com a seguinte nomenclatura:
Originator: É a classe capaz de criar um instantâneo do estado de suas variáveis internas, exportando-o de uma forma que permita a restauração desse estado a qualquer momento. Por consequência, a classe também deve ter uma função que aceite como parâmetro um estado previamente salvo para poder fazer com as variáveis internas da instância da classe assumam os valores contidos nesse parâmetro. No diagrama acima, a classe com essas características é a TWCliente. Repare que as variáveis internas da classe TWCliente são mantidas como privadas (private), sendo acessíveis exclusivamente através dos métodos que realizam as operações dela; isto garante o encapsulamento e o baixo acoplamento em relação à classe que utilizará o recurso de salvar/restaurar o estado dos objetos.

Memento: Armazena todas as informações que forem necessárias para que o estado de uma classe do tipo Originator possa ser restaurado com sucesso. No entanto, a relação das informações que devem ser salvas é determinada pela própria classe Originator. Normalmente, a classe Memento inclui mecanismos para barrar a edição de seu conteúdo, preservando as informações que estão salvas nela para garantir que o estado restaurado é rigorosamente o mesmo que foi salvo. Este papel cabe à classe TWClienteStatus no nosso exemplo.

Caretaker: É a classe que utiliza o recurso de salvar/restaurar de um Originator, determinando o melhor momento para que cada etapa aconteça. Ela, portanto, se relaciona com o Originator, salvando-lhe o estado, realizando operações do Originator através da chamada dos métodos que forem convenientes e restaurando-lhe o estado, se e quando isto for necessário. Para isso, o Caretaker sabe como armazenar uma (ou mais) instância(s) de estados do Originator, mas não tem acesso ao conteúdo salvo nem pode modificá-lo. No exemplo, quem detem esse papel é TWTelaCredito.

Há diferenças em relação ao padrão Command, abordado neste outro post. Enquanto no Command definimos uma interface através da qual ações serão executadas, no Memento a interface é substituída por um mecanismo apenas para salvar o estado atual do objeto e para restaurá-lo quando for necessário. Por causa do uso da interface, polimorfismo é parte importante da solução no Command mas irrelevante na adoção do Memento. É claro que podemos planejar a ação inerente a um Command de um modo que ela também possa ser desfeita. Quando isso ocorre, é comum que ambos os padrões sejam postos para trabalhar em conjunto na mesma solução.

Uma curiosidade: memento é um termo que em latim significa "lembra-te". Em português é pouco usado, mas é o nome que se dá a uma caderneta onde se anota coisas que devem ser lembradas.

No próximo post, eu proponho uma implementação em Delphi para o exemplo usado aqui.

Mais Informações
Posts sobre Design Patterns

Nenhum comentário :

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.