Wzorzec projektowy Obserwator

Problem

Mamy za zadanie zbudować system, który będzie zbierał informacje pogodowe i informował o nich różne jednostki, które na podstawie tych informacji, będą podejmować różne działania.

Z pomocą przychodzi nam wzorzec Obserwator.

Definicja

Wzorzec Obserwator definiuje pomiędzy obiektami relację jeden-do-wielu w taki sposób, że kiedy wybrany obiekt zmienia swój stan, wszystkie jego obiekty zależne zostają o tym powiadomione i automatycznie zaktualizowane.

Rozwiązanie problemu

Observer_classes_pl
Diagram klas wzorca Obserwator
public interface IObserwowany
{
    void DodajObserwatora(IObserwator obserwator);
    void UsunObserwatora(IObserwator obserwator);
    void PowiadomObserwatorow();
}

public interface IObserwator
{
    void Aktualizuj(Pogoda pogoda);
}

We wzorcu obserwator wyróżniamy dwa podstawowe typy obiektów:

  • obserwowany (ang. observable, subject) – obiekt, o którym chcemy uzyskiwać informacje,
  • obserwator (ang. observer, listener) – obiekty oczekujące na powiadomienie o zmianie stanu obiektu obserwowanego.

Na początek stworzymy klasę, która będzie przechowywała informacje o pogodzie i informowała obserwatorów (będzie implementowała interfejs IObserwowany):

 public class SprawdzaczPogody : IObserwowany
 {
     private readonly List<IObserwator> _obserwatorzy;
     private Pogoda _pogoda;

     public SprawdzaczPogody()
     {
          _obserwatorzy = new List<IObserwator>();
     }

     public void DodajObserwatora(IObserwator obserwator)
     {
     _obserwatorzy.Add(obserwator);
 }

 public void UsunObserwatora(IObserwator obserwator)
 {
     _obserwatorzy.Remove(obserwator);
 }

 public void PowiadomObserwatorow()
 {
     foreach (IObserwator obserwator in _obserwatorzy)
     {
         obserwator.Aktualizuj(_pogoda);
     }
 }

 public void Ustaw(Pogoda pogoda)
 {
     _pogoda = pogoda;
     PowiadomObserwatorow();
 }
 }

Następnie przykładowe implementacje obserwatorów:

public class FirmaOgrodnicza : IObserwator
{
    public void Aktualizuj(Pogoda pogoda)
    {
        if (pogoda.Opady == 0 && pogoda.Temperatura > 0)
        {
            Console.WriteLine("Firma Ogrodnicza: Nie ma opadow, mozemy pracowac");
        }
        else
        {
           Console.WriteLine("Firma Ogrodnicza: Nie mozemy pracowac");
        }
    }
}

public class Hotel : IObserwator
{
    public void Aktualizuj(Pogoda pogoda)
    {
        if (pogoda.Zachmurzenie == Zachmurzenie.Bezchmurnie ||
            pogoda.Zachmurzenie == Zachmurzenie.CzescioweZachmurzenie)
        {
            Console.WriteLine("Hotel: Wyciagamy lezaki");
        }
        else if (pogoda.Opady > 0)
        {
            Console.WriteLine("Hotel: To bedzie brzydki dzien, chowamy lezaki");
        }
    }
 }

Wywołanie kodu:

SprawdzaczPogody sprawdzaczPogody = new SprawdzaczPogody();
sprawdzaczPogody.DodajObserwatora(new FirmaOgrodnicza());
sprawdzaczPogody.DodajObserwatora(new Hotel());

sprawdzaczPogody.Ustaw(new Pogoda
{
    Zachmurzenie = Zachmurzenie.Bezchmurnie,
    Temperatura = 25,
    Opady = 0,
    Cisnienie = 1000,
    Wilgotnosc = 50
});
Console.WriteLine();
sprawdzaczPogody.Ustaw(new Pogoda
{
    Zachmurzenie = Zachmurzenie.CalkowiteZachmurzenie,
    Opady = 25,
    Wilgotnosc = 65,
    Temperatura = 10,
    Cisnienie = 987
});

Wynik:

Przechwytywanie

Przy każdej aktualizacji obserwowanego obiektu, dochodzi do powiadomienia obserwatorów, dzięki czemu mogą oni podjąć odpowiednie działania.

Jak widać, wzorzec jest bardzo prosty w implementacji. Może jednak zaoszczędzić wiele

Podsumowanie

  • Definiuje relację jeden-do-wielu pomiędzy obiektami.
  • Obiekty obserwujące są luźno powiązane z obiektem obserwowanym, co oznacza, że obiekt obserwowany wie o nich tyle, na ile pozwala interfejs.
  • Nie można uzależniać poprawnego funkcjonowania aplikacji od określonego kolejności powiadamiania przesyłanego do obiektów obserwujących.
Reklamy

2 uwagi do wpisu “Wzorzec projektowy Obserwator

    1. Po części tak. Wydaje mi się, że wzorzec ten powstał zanim powstały eventy.
      Zaletą stosowania tego wzorca jest to, że implementując samodzielnie interfejsy, mamy większą kontrolę nad przebiegiem programu. Możemy dodawać jakieś warunki, zmieniać zachowanie itp. Jednak wadą to, że musimy implementować cały interfejs IObserwowany, a eventy zapewniają nam to na wejściu.

      Polubienie

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

w

Connecting to %s