11 de novembro de 2010

Design Patterns em Delphi – Mediator

Na modelagem de sistemas computacionais encontramos às vezes situações em que diversas classes de objetos podem ter que interagir entre si para que uma determinada ação seja concluída com sucesso. São cenários onde as classes têm relacionamento de muitos para muitos, isto é, as classes envolvidas podem se comunicar com qualquer uma das outras. O impulso inicial é o de incluir no modelo relacionamentos diretos entre todas as classes, tornando-as fortemente acopladas. Portanto, ter que adicionar novas classes a esse tipo de interação implicará a existência de uma profusão de relacionamentos, tornando complexa a manutenção da funcionalidade no sistema.

Esse tipo de situação ocorre, por exemplo, com as relações entre componentes visuais numa tela. Imagine que você queira fazer com que alterações no conteúdo de um componente reflitam em outros. Ao informar um código numa caixa de edição, por exemplo, a tela deve trazer dados sobre um Cliente, um Produto ou uma Conta a Pagar e esses dados devem alimentar outras caixas de edição, combos, checkboxes, etc. Ou, ao apertar um botão, a tela usar filtros informados em outros componentes, submeter uma query ao banco de dados e popular um grid. Qualquer componente pode se comunicar com todos os outros ! Criar novos componentes ampliaria a quantidade de relacionamentos possíveis, alavancando junto a complexidade de manutenção do sistema.

Linguagens de programação visuais modernas resolvem essa situação particular com eventos. O Design Pattern comportamental Mediator propõe resolver esta questão centralizando numa única classe a responsabilidade pela comunicação de todas as outras envolvidas na solução de um problema. Em outras palavras, o Mediator encapsula o modo como as classes interagem, desacoplando-as ao evitar que elas tenham que manter referências explícitas entre si. A ideia é a mesma de uma torre de controle de tráfego aéreo. Qualquer aeronave que queira decolar ou pousar tem antes que se comunicar com a torre para obter permissão. Esta comunicação mediada é muito mais simples e eficiente do que se cada aeronave tivesse que conversar diretamente com todas as outras para determinar o melhor momento de realizar sua manobra. Além disso, estabelecer que a comunicação deva ser mediada pela torre permite que um número indefinido de aeronaves seja controlado sem que haja necessidade de umas terem conhecimento da existência das outras.

Veja abaixo um diagrama UML retratando a solução proposta pelo Mediator para o exemplo do tráfego aéreo:
Diagrama UML para o padrão Mediator

Mesmo tendo apenas 3 classes de aeronaves modeladas, a torre é planejada para comportar um número indefinido de instâncias ao mesmo tempo. Adicionar novos tipos de aeronaves fica simplificado pois a nova classe só tem que aprender a conversar com o mediador (a torre), sem precisar saber quantas ou quais são as outras aeronaves presentes num determinado instante.

A nomenclatura formal para as classes participantes desse tipo de solução está retratada no quadro a seguir:
O Mediator é uma classe abstrata que define o padrão de comunicação que estará disponível para os objetos que serão administrados por ele. No exemplo do diagrama acima este papel cabe à classe TWTorreAbstrata.
Dá-se o nome de ConcreteMediator a toda herança que implementa as regras de comunicação estabelecidas pela classe Mediator. Estas heranças são, portanto, efetivamente responsáveis por coordenar a comunicação entre os objetos associados a elas. No diagrama de exemplo há apenas uma classe desse tipo: a TWTorreAeroportoCGH.

Cenários distintos exigirão a implementação de heranças distintas capazes de prover a comunicação apropriada entre os seus membros. No caso dos componentes de tela, por exemplo, podemos criar novas telas (mediadores) com seu próprio conjunto de componentes e codificarmos nelas as relações específicas entre esses componentes.
O AbstractColeague determina o comportamento padrão esperado para todos os objetos que desejam se comunicar entre si através do mediador. Por isso, tal classe terá que armazenar uma referência ao objeto mediador e acessá-lo sempre que necessitar se comunicar com as demais instâncias. Esse é o papel da classe TWAeronaveAbstrata no diagrama acima.
Os ConcreteColeagues implementam o comportamento determinado pela classe Coleague, enquanto realizam suas tarefas particulares. Se uma classe desse tipo precisar se comunicar com os demais Coleagues de uma forma nova, terá que fazê-lo também através do mediador, ainda que isto implique o uso de um ConcreteMediator específico. As classes TWBoing, TWTecoTeco e TWJatoExecutivo pertencem a esta categoria.

Num próximo post eu publico a codificação em Delphi do exemplo usado aqui para ilustrar esse Design Pattern.

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.