Atenção: esse artigo tem uma palestra complementar. Clique e assista!
Aprenda como integrar as partes do seu sistema de maneira sofisticada. Através do uso das interfaces o Padrão Observer permite que partes distintas se comuniquem sem que uma parte precise conhecer a outra.
Para que serve
Com o Padrão Observer você consegue criar um sistema realmente integrado, pois cada parte do seu sistema será notificado sempre e somente se necessário sobre as mudanças de outras partes. Integração quer dizer que a aplicação funciona de maneira diferente de acordo com o que está acontecendo em cada pedaço do sistema.
Em que situação o tema é útil
A palavra chave é integração. Quando se deseja integrar partes do seu sistema sem que seja criado forte acoplamento entre elas, de tal forma que as partes envolvidas se interajam apenas quando for necessário e não em determinados espaços de tempo.
Resumo do DevMan
Sistemas modernos precisam deixar o usuário informado sobre as mudanças que ocorrem em seu ambiente em tempo real. É isto que se espera de um sistema que se diga integrado. Um bom exemplo para isto é um sistema que possua controle de estoque. Normalmente estes sistemas possuem um algoritmo para fazer o balanço do estoque da empresa. Quando o balanço é iniciado muitas funções do sistema ligadas ao movimento de estoque devem ficar indisponíveis até que o balanço termine. Muitas vezes este controle não é feito e fica sendo responsabilidade do usuário cuidar para que nenhuma venda ocorra durante o processo de balanço. Neste artigo você vai aprender o que fazer para que as partes do seu sistema interajam entre si de maneira elegante, através do padrão Observer.
O padrão Observer garante que as partes específicas de um sistema sejam notificadas de mudanças que acontecem em alguma área do sistema, porém, sem que estas duas partes saibam muito uma da outra, ou seja, a tela de vendas pouco ou nada saberia a respeito do objeto Produtos, mas de alguma maneira seria informada quando o objeto Produtos iniciar a rotina de balanço de estoque.
Entenda o que é um sistema integrado
Imaginando o cenário proposto no quadro Resumo do DevMan, uma das soluções para que o módulo de vendas fique ciente de que o processo de balanço está ativo, é implementar uma verificação pelo uso do TTimer, onde em um período estabelecido, o sistema verificaria se o balanço está sendo feito. Apesar desta ser uma solução comum, não é a mais indicada visto que um número excessivo de solicitações estarão acontecendo desnecessariamente, além do fato de que existe um intervalo de tempo entre uma solicitação e outra. Imagine a seguinte situação:
• O usuário Marcos abre o formulário de venda;
• A usuária Jaqueline, abre a janela de balanço, mas ainda não o inicia;
• O TTimer, no computador do Marcos, faz uma verificação para garantir que nenhum balanço foi iniciado;
• Jaqueline inicia o balanço;
• Marcos, salva a venda, o que não devia ser permitido porque a Jaqueline iniciou o balanço;
• O TTimer, no computador do Marcos, faz a verificação novamente e agora como o balanço foi iniciado, desabilita o uso da venda para o Marcos, porém, faz isto tarde demais, pois Marcos já fez uma venda quando existia um balanço em andamento.
Neste simples exemplo você pode ver como é frágil um sistema cujas partes são integradas usando um TTimer. Você pode diminuir a possibilidade disso acontecer diminuindo o intervalo de tempo, mas isto traz outra consequência: com o uso excessivo de TTimers você faz seu sistema parecer mais lento, já que um processamento extra é executado a cada X milissegundos. Pense no TTimer como um objeto “burro”, pois ele não sabe quando a informação mudou e faz verificações repetidas vezes mesmo que nada tenha mudado. Pior do que usar TTimer para integrar as partes do sistema é não integrar o sistema.
O Padrão Observer
Busque projetos levemente ligados entre objetos que interagem.
Integrar as partes do sistema não é uma tarefa simples, principalmente quando você tem um sistema que funciona em rede com múltiplos usuários logados ao mesmo tempo. O problema do processo de integração é fazer com que as diversas partes do sistema conversem entre si. Isto é realmente um problema, pois em um mundo orientado a objetos os sistemas devem ser construídos de maneira que uma parte conheça o mínimo ou até mesmo não conheça a outra parte. Então fica a dúvida: como a parte X pode saber se algo mudou na parte Y se o X não pode conhecer o Y? Colocar um TTimer seria declarar descaradamente que as duas partes se conhecem, pois a parte com o TTimer terá que conhecer os detalhes da parte que será verificada. Felizmente outros programadores já passaram por este problema e documentaram a solução que encontraram. Para esta solução eles deram o nome de Padrão Observer.
O exemplo
Para explicar o Padrão Observer, vou criar durante este artigo uma pequena aplicação de exemplo. Esta aplicação terá duas funções: vender e fazer balanço do estoque. Não será muito complexo, pois o objetivo do artigo não é ensinar a criar uma rotina de venda ou de balanço, mas sim de ensinar como fazer para que estas e outras partes do sistema possam se comunicar para se tornar uma integração de verdade.
Obviamente esta será uma aplicação orientada a objetos, então os objetos envolvidos no problema devem ser encontrados antes de começar a aplicação. O problema que precisa ser solucionado é: fazer vendas e balanço de estoque. Eu encontrei dois objetos envolvidos neste problema, são eles: TVenda e TBalanco. Eu pensei na classe TVenda para solucionar o problema de se fazer vendas e na classe TBalanco para fazer o balanço de estoque da empresa. Não posso me esquecer também do formulário principal da aplicação, pois sem ele o usuário não consegue usar o sistema. Então são três classes, contando com o formulário principal, para resolver o problema de venda e balanço de estoque: TVenda, TBalanco e TFormPrincipal. Veja na Figura 1 o diagrama de classes da aplicação.
Figura 1. As classes do sistema de exemplo
Você pode notar duas informações importantes no diagrama de classes: o formulário principal depende das classes TBalanco e TVenda para existir e as classes TBalanco e TVenda não se conhecem. O formulário principal será tão simples quanto o exemplo que está sendo criado. Nele existirão quatro botões: um para iniciar a venda, um para finalizá-la, um para iniciar o balanço e um último para finalizá-lo, além de dois componentes TLabel para indicar se existe alguma venda ou balanço iniciado. Veja na ...