Wzorce projektowe (18)

Autor: Damian Chodorek • Opublikowany: 24 lipca 2015 • Kategoria: kursy, wzorce projektowe

Obserwator.

Obserwator to wzorzec obiektowy. Jego celem jest powiadamianie zainteresowanych obiektów o zmianie stanu innego obiektu.

Klasy

class Observable{/*
abstrakcyjna klasa, która definiuje metody odpowiedzialne za dodawanie i usuwanie obserwatorów oraz za powiadamianie zainteresowanych
*/};

class ConcreteObservable: public Observable{/*
klasa konkretnych obiektów obserwowanych, jeśli któryś zmieni swój stan, powiadomi o tym wszystkich obserwujących
*/};

class Observer{/*
abstrakcyjna klasa deklarująca aktualizację własnego stanu
*/};

class ConcreteObserver: public Observer{/*
konkretny obserwator, definiuje metodę odpowiadającą za aktualizację swojego stanu
*/};

Etapy działania

  1. Klient tworzy obserwowanego i obserwujących.
  2. Do obiektu obserwowanego podpina obiekty obserwujących.
  3. Jeśli obiekt obserwowany zmieni swój stan, powiadomi o tym podpiętych obserwujących.
  4. Reakcja na powiadomienie należy do samych obserwujących.

Konsekwencje

Zalety:

  • ponieważ obiekt obserwujący i obserwowany nie wiedzą wiele o sobie nawzajem, mogą być niezależnie modyfikowane,
  • relacja między obserwatorem i obserwowanym tworzona jest podczas działania programu i może być zmieniana
    dynamicznie,
  • domyślnie obserwowany powiadamia wszystkich obserwatorów; oni sami decydują czy obsłużyć fakt powiadomienia.

Wady:

  • Obserwatorzy nie znają innych obserwatorów, to może wywołać trudne do znalezienia skutki uboczne.

Przykład

#include <iostream>
#include <string>
#include <list>

using namespace std;

//Obserwator:
class Observer {
public:
    virtual void update() = 0;
    virtual ~Observer() {}
};

//Obserwowany:
class Observable {
protected:
    list <Observer*> observers;
public:
    void attach (Observer *o) {
        observers.push_back (o);
    }
    void detach (Observer *o) {
        observers.remove (o);
    }
 
    void notify () {
        list<Observer *>::iterator it;
        for (it = observers.begin(); it != observers.end(); it++) {
            (*it)->update ();
        }
    }
};

//Obserwowany Konkretny:
class Honey {
protected:
    int quantity;
public:
    Honey (int q) {
        quantity = q;
    }
 
    int getQuantity () {
        return quantity;
    }
 
    void setQuantity (int q) {
        quantity = q;
    }
};

// wielokrotne dziedziczenie jest często wykorzystywane w tym wzorcu
class ObservableHoney : public Observable, public Honey {
    string state;
public:
    ObservableHoney (int q) : Honey(q) {
    }
 
    string getState () {
        return state;
    }
 
    void setState (const string& s) {
        state = s;
        cout << "Stan: " << state << endl;
        notify();
    }
};


//Obserwator Konkretny:
class ObserverBear : public Observer {
protected:
    int bearId;
    ObservableHoney *honey;
public:
    ObserverBear (ObservableHoney *h, int id) {
        honey = h;
        bearId = id;
    }
    void update () {
        string state = honey->getState();
        if (!state.compare ("Sa ludzie blisko miodu")) {
            cout << "Mis" << bearId << ": Czekam w ukryciu" << endl;
        } else if (!state.compare ("Nie ma ludzi blisko miodu")) {
            cout << "Mis" << bearId << ": Kradne miod" << endl;
            honey->setQuantity(honey->getQuantity()-1);
        } else if (!state.compare ("Ida ludzie")) {
            cout << "Mis" << bearId << ": Uciekam" << endl;
        }
    }
};


//Przyklad uzycia:
int main() {
    ObservableHoney honey (5);
    Observer *bear1 = new ObserverBear(&honey, 1);
    Observer *bear2 = new ObserverBear(&honey, 2);
 
    honey.attach(bear1);
    honey.attach(bear2);
 
    cout << "Ilosc miodu: " << honey.getQuantity() << endl;
 
    honey.setState("Sa ludzie blisko miodu");
    honey.setState("Nie ma ludzi blisko miodu");
    honey.setState("Ida ludzie");
 
    cout << "Ilosc miodu: " << honey.getQuantity() << endl;
    delete bear1;
    delete bear2;
    return 0;
}

część 19

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.