19 de fevereiro de 2010

Design Patterns com Delphi : Chain Of Responsability

Já comentei aqui no blog a respeito dos Design Patterns Criacionais (relativos à forma como os objetos são criados num programa) e dos Estruturais (que abordam as associações estruturais entre classes e objetos, isto é, os relacionamentos entre as classes para garantir a coesão de um projeto). Ficaram faltando ainda os Design Patterns Comportamentais, que são aqueles que se preocupam com as interações existentes entre objetos. Essas interações devem ser concebidas de maneira que os objetos possam trocar mensagens entre si (se comunicar) e ainda assim permanecerem fracamente acoplados, isto é, sem que uns tenham dependências rígidas com os outros ou que tenham que conhecer detalhes profundos da implementação uns dos outros.

O primeiro desses padrões que tratarei aqui é Cadeia de Responsabilidade. Nele, a requisição feita por um objeto Cliente é transmitida ao longo de uma sequência de Classes até que a requisição seja suprida por uma delas. Como a ideia é manter as classes o mais desacopladas possível, esse tipo de transmissão da mensagem (requisição) é baseado no conceito de "orientação a dados", ou seja, a estruturação dos dados trafegados na mensagem é o único ponto de contato entre as classes. Aquela Classe que recebe a mensagem deve analisar os dados recebidos e, se não for capaz de atender à requisição, ela deverá retransmitir a mensagem para o objeto seguinte na hierarquia.

Exemplos típicos da aplicação do padrão Cadeia de Responsabilidade envolvem alçadas de aprovação. Imagine, por exemplo, o sistema de compras de uma companhia, onde os Compradores podem submeter os pedidos de compra sem necessitar uma aprovação se o pedido tiver certas características (digamos, um limite máximo de valor) mas que, conforme estas características vão variando, o pedido deve ser submetido a aprovação por níveis hierárquicos cada vez mais altos (supervisor, gerente, diretor, presidente).

O diagrama abaixo mostra as classes participantes da solução para esse cenário utlizando a Cadeia de Responsabilidade.
Diagrama UML para Chain Of Responsability
A nomenclatura das classes participantes da solução é descrita no quadro abaixo:
Handler é a classe que descreve a interface que é disponibilizada para aqueles que pretendem submeter uma requisição. Ou seja, é uma classe abstrata que apenas oferece os pontos de entrada para as requisições que poderão ser feitas; as transações que forem utilizá-la não saberão de antemão quais nem quantos são os níveis hierárquicos existentes, tampouco as regras aplicadas. No diagrama acima, este é o papel da classe TWAprovacao.
É preciso que outras classes sejam criadas para implementar a interface publicada pelo Handler. Essas classes são chamadas de Concrete Handlers, sendo exemplos as classes TWAprovacaoBasica e TWAprovacaoGerente no diagrama. Repare que apenas observando o diagrama não é possível determinar a hierarquia da cadeia de responsabilidades. Isso terá que ser montado através de algum dos padrões criacionais, num ponto em que inevitavelmente teremos que introduzir regras de negócio.
Por fim, a classe que submete uma requisição à Cadeia de Responsabilidades é chamada de Client. A classe TWbusinessObj tem essa função no nosso exemplo.
A classe TWDocumento representa um documento genérico do meu sistema, podendo ser um Pedido de Compra ou de Venda, uma Nota Fiscal, etc.. Ela é o ponto de contato entre a transação representada pelo objeto de negócio TWbusinessObj e a hierarquia de classes da Cadeia de Responsabilidade. Portanto, neste exemplo o TWDocumento é o dado que trafega pelos elos da cadeia permitindo que cada classe tenha subsídios para determinar se a mensagem é de sua responsabilidade ou se ela deve ser retransmitida.

No próximo post eu apresento uma forma de codificar essa solução usando Delphi.

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.