Antes de falar do Observer é necessário entender o que é Design Pattern, ou padrão de desenho de software, eles descrevem soluções para problemas recorrentes no desenvolvimento de sistemas que utilizam a O.O. – Orientação a Objetos. Um padrão define um problema, a solução deste problema, a situação onde aplicar esta solução e suas conseqüências e o nome deste.
Designs Patterns visam facilitar a reutilização de código, também apresentam um vocabulário comum de desenho facilitando comunicação, documentação e aprendizado dos sistemas.
Agora sim vamos falar um pouco de um dos padrões, o Observer é um Design Pattern, traduzindo é um padrão de desenvolvimento que representa uma relação de 1-N (de um para muitos) entre objetos. Assim quando um objeto muda de estado os objetos dependentes serão notificados/informados e atualizados automaticamente. Este padrão permite que objetos sejam avisados da mudança de estado de outros eventos ocorrendo num outro objeto.
Observer é também chamado de Publisher-Subscriber, Event Generator e Dependents.
As classes participantes e/ou objetos participantes deste padrão são:
- Subject (Stock)
– Conhece os Observers. Qualquer número de objetos Observer pode observar um Subject.
– Fornece interfaces para anexar e desanexar objetos Observer. - ConcreteSubject (IBM)
– Armazena estado de interesse para o ConcreteObserver.
– Envia a notificação para os observers quando o status muda. - Observer (IInvestor)
– Define uma interface de atualização para objetos que devem ser notificados de mudanças em um Subject. - ConcreteObserver(Investor)
– Mantém uma referência a um objeto ConcreteSubject.
– Armazena o estado que deve ficar consistente com o Subject.
– Implementa a interface Observer atualizando para manter o estado consistente com o Subject.
Para esta demonstração utilizarei como linguagem de programação C#, e como ferramenta de compilação e testes o Visual Studio 2008 com o .Net Framework 3.5. Apenas pra deixar clara a forma que foi construída. Neste post você poderá também efetuar o download do projeto e fazer os testes e alterações que desejar.
Em um projeto WindowsForms mesmo, para apresentação do funcionamento, crio a seguinte classe que desempenhará o papel do Subject:
public abstract class Stock { private string m_symbol; private double m_price; private List<IInvestor> m_investors = new List<IInvestor>(); public Stock(string symbol, double price) { this.m_symbol = symbol; this.m_price = price; } public void Attach(IInvestor investor) { m_investors.Add(investor); } public void Detach(IInvestor investor) { m_investors.Remove(investor); } public void Notify() { foreach (IInvestor investor in m_investors) investor.Update(this); } public double Price { get { return m_price; } set { if (m_price != value) { m_price = value; Notify(); } } } public string Symbol { get { return m_symbol; } } }
Em seguida adiciono uma nova classe que herda da classe abstrata criada, esta desempenhará o papel da ConcreteSubject.
public class IBM : Stock { public IBM(string symbol, double price) : base(symbol, price) { } }
A próxima classe a ser inserida é classe que desempenhará o papel do observer, ela é uma interface:
public interface IInvestor { void Update(Stock stock); }
Por fim adiciono a classe Investor que desempenha o papel do ConcreteObserver, herdando portanto da interface criada.
public class Investor : IInvestor { private string m_name; private Stock m_stock; public Investor(string name) { this.m_name = name; } public void Update(Stock stock) { MessageBox.Show("Notificação: (" + m_name + ") de " + stock.Symbol + ".O preço foi alterado para " + stock.Price.ToString("0.00")); } public Stock Stock { get { return m_stock; } set { m_stock = value; } } }
Com isso já é possível utilizar a estrutura para os devidos testes.
Como o projeto criado é do tipo WindowsForms no evento load do formulário incluo o seguinte código:
private void Form1_Load(object sender, EventArgs e) { IBM ibm = new IBM("IBM", 100.00); ibm.Attach(new Investor("Acionista A")); ibm.Attach(new Investor("Acionista B")); /* depois de ter realizado o Attach, a cada vez que atribuir um novo preço para ibm, cada um dos investidores será notificado. */ ibm.Price = 200.10; ibm.Price = 500.00; this.Close(); }
Pronto! Agora é só compilar, adicionar as devidas referências que por ventura possam estar faltando. E o resultado será 4 MessagesBox, pois para cada alteração de preço, existe 2 Investor para serem notificados.
As mensagens apresentadas serão como as Figuras 1,2,3 e 4 apresentadas abaixo:
Apresentando como fica a estrutura dos arquivos em Solution Explorer:
E como dito anteriormente segue em anexo o arquivo compactado com a solução para baixar, e ajudar no entendimento.
Download Fonte aqui