Observer

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:

  1. Subject (Stock)
    – Conhece os Observers. Qualquer número de objetos Observer pode observar um Subject.
    – Fornece interfaces para anexar e desanexar objetos Observer.
  2. ConcreteSubject (IBM)
    – Armazena estado de interesse para o ConcreteObserver.
    – Envia a notificação para os observers quando o status muda.
  3. Observer (IInvestor)
    – Define uma interface de atualização para objetos que devem ser notificados de mudanças em um Subject.
  4. 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.
  5. 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