Vamos falar do padrão Observer, na minha opinião é um dos mais interessantes, imagina manter os objetos atualizados quando acorrer algo em um objeto importante. E vamos ver ligações leves entre objetos uma boa pratica de programação, então vamos lá.

Para entendermos o padrão Observer, vamos pensar como funciona uma Editora (Observado) de jornal, eles tem uma lista de clientes (Observadores), quando sai uma nova publicação todos os observadores recebem uma copia do jornal, sendo que a qualquer momento um novo cliente(Observador) pode se registrar ou os clientes atuais cancelarem o registro.

Bom, o padrão Observer é isso, um objeto (Observado) que permite que outros objetos sejam registrados  como observadores ou cancelar o seu registro a qualquer momento da aplicação, e ressaltando a ligação leve entre o objeto observado e seus observadores, com isso os objetos podem interagir, mas não sabem quase nada um sobre o outro, deixando bem flexível os objetos observadores e observados.

Pensando em uma aplicação pratica, vamos criar rede de fabricação de automóveis, onde vamos ter duas montadoras (observados) e varias fabricas(observadores) e prestadora de serviços(observadores), observe que teremos 2 classes que farão o papel de observador (poderíamos ter “n” classes diferentes), onde os fabricas e prestadoras vão se registrar em uma ou mais montadoras e sempre que a montadora receber um novo pedido os observadores vão receber uma notificação com a quantidade.

Vimos aqui uma dependência um-para-muitos, esse processo de registro e cancelamento do registro será feito em tempo de execução, podendo a qualquer momento ficar observando ou não uma montadora, e/ou observar mais de uma montadora simultaneamente.

No exemplo abaixo demonstro como implementar essa solução, um outro ponto importante é que existem varias formas de implementar qualquer padrão, o que devemos entender de cada um é o conceito, contexto e aplicação.

Temos que criar um EventArgs para passagem dos parâmetros e a interface para os observadores e observados se comunicarem, visto que esse é o único canal e ligação entre observador e observado.

// Argumentos para os Eventos

public class ChangeEventArgs : EventArgs

{

    public String Nome { get; set; }

    public int Pecas { get; set; }

}

 

// A interface para os observadores

public interface IObservador

{

    String _Nome { get; set; }

    void Update(object sender, ChangeEventArgs e);

}

Todas as classes que querem observar deve implementar a interface IObservador, lembra da ligação leve, muito bem essa é nossa ligação leve, o observador não sabe o observado faz e nem o observado sabe o que o observador faz, a única coisa que um sabe sobre o outro é que quando houver uma alteração no observado o observador vai ser notificado, isso vai ser feito pelo método “Update”.

Vamos criar uma classe abstrata para os observados, aqui vamos definir o método para registro de observadores e o método de cancelamento, e também a chamada para notificar os observadores.

// Classe abstrata para criação da montadoras (observados)

public abstract class Montadora

{

    protected String _Nome;

    protected int _Pecas;

 

    // Construtor

    public Montadora(string Nome)

    {

        this._Nome = Nome;

    }

 

    // Evento

    protected event EventHandler<ChangeEventArgs> Change;

 

    // Invoke do evento

    protected virtual void OnChange(ChangeEventArgs e)

    {

        if (Change != null)

        {

            Change(this, e);

        }

    }

 

    //Metodo para registrar observadores

    public void Registrar(IObservador Observador)

    {

        Change += Observador.Update;

        Console.WriteLine("{0} registrado(a) com sucesso na montadora {1}", Observador._Nome, this._Nome);

    }

 

    //Médoto para cancelar observadores

    public void Cancelar(IObservador Observador)

    {

        Change -= Observador.Update;

        Console.WriteLine("{0} cancelado(a) com sucesso na montadora {1}", Observador._Nome, this._Nome);

    }

 

    protected int Pecas

    {

        get { return _Pecas; }

        set

        {

            if (_Pecas != value)

            {

                _Pecas = value;

                OnChange(new ChangeEventArgs { Nome = _Nome, Pecas = _Pecas });

                Console.WriteLine("");

            }

        }

    }

}

É importante ressaltar o EventHendler Change, pois é nele que é contido os médotos Update dos observadores para ser delegado o envio da notificações, temos também os métodos Registrar e Cancelar que recebe um objeto que assina a interfece IObservador. São nestes métodos que são feitos os controles sobre os observadores e a notificações.

Criaremos uma classe concreta de Montadora com o método NovoPedido, na classe abstrata Montadora temos uma propriedade Pecas e este quando alterado dispara a notificação para os observadores.

// A classe concreta do observado, podendo ter variações de classe para classe, uma vez que estamos utilizando ligação leve.

public class Montadora1 : Montadora

{

    public Montadora1(String Nome)

        : base(Nome) { }

 

    public void NovoPedido(int QtdPedido)

    {

        Console.WriteLine("\nTemos um pedido de {0} iten(s). Observado: {1}\n", QtdPedido, this._Nome);

        this.Pecas = QtdPedido;

    }

}

Podemos criar vários objetos dessa classe, como também podemos criar outras classes herdando Montadora.

Agora vamos criar duas classes assinando a interface IObservador, uma classe para as fabricas e uma para as prestadoras de serviços.

// A classe concreta para observadores do tipo Fabrica

public class Fabrica : IObservador

{

    public String _Nome { get; set; }

    public String _Produto { get; set; }

    public int _qtdProducao { get; set; }

 

    public Fabrica(String Nome, String Produto, int QtdProduto)

    {

        this._Nome = Nome;

        this._Produto = Produto;

        this._qtdProducao = QtdProduto;

    }

 

    public void Update(object sender, ChangeEventArgs e)

    {

        Console.WriteLine("A montadora {0}, solicitou {1} {2}. Observador: {3}", e.Nome, e.Pecas * this._qtdProducao, this._Produto, this._Nome);

    }

}

 

// A classe concreta para observadores do tipo Serviços

public class Servicos : IObservador

{

    public String _Nome { get; set; }

    public String _Servico { get; set; }

 

    public Servicos(String Nome, String Servico)

    {

        this._Nome = Nome;

        this._Servico = Servico;

    }

 

    public void Update(object sender, ChangeEventArgs e)

    {

        Console.WriteLine("A montadora {0}, solicitou {1} de {2} itens. Observador: {3}", e.Nome, this._Servico, e.Pecas, this._Nome);

    }

}

Repito, todas as classes que assinarem a Interface IObservador poderão observar.

Com tudo implementado, vamos aos testes.

class Program

{

    static void Main(string[] args)

    {

        ///Criando 2 montadoras.

        Montadora1 MontadoraCarros = new Montadora1("MontCarros");

        Montadora1 MontadoraCaminhoes = new Montadora1("MontCaminhões");

 

        ///Criando 2 Fabricas e 1 Servico

        Fabrica FabricaRodas = new Fabrica("RodasOuro", "rodas", 4);

        Fabrica FabricaMotores = new Fabrica("MotorTurbo", "motores", 1);

        Servicos ServicoPintura = new Servicos("SprayJato", "pintura");

 

        ///Registrando Fabricas na montadora de Carros

        MontadoraCarros.Registrar(FabricaRodas);

        MontadoraCarros.Registrar(FabricaMotores);

 

        ///Registrando Fabrica e Servico na montadora de Caminhoes

        MontadoraCaminhoes.Registrar(FabricaMotores);

        MontadoraCaminhoes.Registrar(ServicoPintura);

 

        ///Enviando pedidos para as montadoras

        MontadoraCarros.NovoPedido(2);

        MontadoraCaminhoes.NovoPedido(100);

 

        ///Cancelando um registro na montadora de carros

        MontadoraCarros.Cancelar(FabricaRodas);

        ///Registrando um servico na montadora de carros

        MontadoraCarros.Registrar(ServicoPintura);

        ///Enviando um novo pedido para a montadora de carros

        MontadoraCarros.NovoPedido(19);

 

        ///Cancelando 1 fabrica e 1 servico da montadora de carros

        MontadoraCarros.Cancelar(FabricaMotores);

        MontadoraCarros.Cancelar(ServicoPintura);

 

        ///Enviando um novo pedido para a montadora de carros

        MontadoraCarros.NovoPedido(3);

 

        ///Registrando Fabricas e Servicos na montadora de Carros

        MontadoraCarros.Registrar(FabricaRodas);

        MontadoraCarros.Registrar(FabricaMotores);

        MontadoraCarros.Registrar(ServicoPintura);

 

        ///Enviando um novo pedido para a montadora de carros

        MontadoraCarros.NovoPedido(4);

 

        ///Enviando um novo pedido para a montadora de Caminhoes

        MontadoraCaminhoes.NovoPedido(6);

 

        Console.ReadKey();

    }

}

Observe que temos duas montadoras, duas fabricas e uma prestadora de serviço.

Não deixem de fazer o download do exemplo para um maior estudo, espero que tenha conseguido passar o conceito do padrão Observer.

 

Fontes:

FREEMAN, ERIC & FREEMAN, ELISABETH – Use a Cabeça! Padrões de Projetos (Design Patterns), 2ª Edição [http://www.livrariasaraiva.com.br/produto/1995765/]