Artmetic Qt/C++ Wzorzec obserwator C++/Qt

Wzorzec obserwator C++/Qt

obserwator C++

Często się zdarza że programiści napotykają problem we współczesnych programu posiadające interfejs użytkownika (GUI), muszą reagować na zmiany danych w kilku różnych miejscach jednocześnie. Do sytuacji takiej może dojść wtedy gdy pracujemy na tych samych danych, które możemy edytować w kilku miejscach jednocześnie np. wykresy obrazujące takie same dane. Zmiana wartości na jednym wykresie implikuje zmianę wartości na pozostałych wykresach.

W przypadku kiedy mamy do czynienia z kilkoma obiektami możemy wykorzystać mechanizm sygnałów i slotów w Qt, jednak jeżeli jednak liczba obserwowanych obiektów, które się zmieniają nie jest zdefiniowana lub dotyczy znacznej grupy obiektów możemy zbudować osobną klasę zwaną Obserwatorem mającą na celu powiadamianie obiektów o występujących zmianach.

Pomimo że istnieje wiele różnych implementacji tego samego wzorca mają one elementy wspólne takie jak:

Wszystkie z obiektów można podzielić na dwie osobne grupy wydawców i klas pełniących rolę obserwatorów
Każda z implementacji zakłada że jest jeden obiekt, które informuje inne obiekty o zmianach
Mechanizm wysyłania informacji do pozostałych klas jest zdefiniowany w całości w klasie bazowej wydawcy.

Zalety i wady

Zalety:

Luźna zależność między obiektem obserwującym i obserwowanym. Ponieważ nie wiedzą one wiele o sobie nawzajem, mogą być niezależnie rozszerzane i rozbudowywane bez wpływu na drugą stronę.
Relacja między obiektem obserwowanym a obserwatorem tworzona jest podczas wykonywania programu i może być dynamicznie zmieniana.
Możliwość zablokowania klientowi drogi do bezpośredniego korzystania ze złożonego systemu, jeśli jest to konieczne.

Wady:

Obserwatorzy nie znają innych obserwatorów, co w pewnych sytuacjach może wywołać trudne do znalezienia skutki uboczne.
Zastosowanie

Wzorzec Obserwatora sprawdza się wszędzie tam, gdzie stan jednego obiektu uzależniony jest od stanu drugiego obiektu.

Implementacja

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

class Obserwowany {
protected:
std::list <obserwator*> obserwatorzy;
public:
void dodaj(Obserwator *o) {
obserwatorzy.push_back (o);
}
void usun(Obserwator *o) {
obserwatorzy.remove (o);
}</obserwator*>

void powiadom () {
std::list<obserwator *="">::iterator it;
for (it = obserwatorzy.begin(); it != obserwatorzy.end(); it++) {
(*it)-&gt;update ();
}
}
};

Obserwowany Konkretny:

Dziedziczenie wielokrotne dostępne w C++ jest często używane w wzorcu Obserwatora

class Miod {
protected:
int ilosc;
public:
Miod (int q) {
ilosc = q;
}

int pobierzIlosc () {
return ilosc;
}

void ustawIlosc (int q) {
ilosc = q;
}
};

class ObserwowanyMiod : public Obserwowany, public Miod {
std::string stan;
public:
ObserwowanyMiod (int q) : Miod(q) {
}

std::string pobierzStan () {
return stan;
}

void ustawStan (const std::string&amp; s) {
stan = s;
std::cout &lt;&lt; "Stan: " &lt;&lt; stan &lt;&lt; std::endl;
        powiadom();
    }
};

Obserwator Konkretny:

class ObserwatorMis : public Obserwator {
protected:
int misId;
ObserwowanyMiod *miod;
public:
ObserwatorMis (ObserwowanyMiod *h, int id) {
miod = h;
misId = id;
}
void update () {
std::string stan = miod-&gt;pobierzStan();
if (!stan.compare ("Sa ludzie blisko miodu")) {
std::cout &lt;&lt; "Mis" &lt;&lt; misId &lt;&lt; ": Czekam w ukryciu" &lt;&lt; std::endl;
        } else if (!stan.compare ("Nie ma ludzi blisko miodu")) {
            std::cout &lt;&lt; "Mis" &lt;&lt; misId &lt;&lt; ": Kradne miod" &lt;&lt; std::endl;
            miod-&gt;ustawIlosc(miod-&gt;pobierzIlosc()-1);
} else if (!stan.compare ("Ida ludzie")) {
std::cout &lt;&lt; "Mis" &lt;&lt; misId &lt;&lt; ": Uciekam" &lt;&lt; std::endl;
        }
    }
};

Przykład użycia:

int main() {
ObserwowanyMiod miod (5);
Obserwator *mis1 = new ObserwatorMis(&amp;miod, 1);
Obserwator *mis2 = new ObserwatorMis(&amp;miod, 2);

miod.dodaj(mis1);
miod.dodaj(mis2);

std::cout &lt;&lt; "Ilosc miodu: " &lt;&lt; miod.pobierzIlosc() &lt;&lt; std::endl;

    miod.ustawStan("Sa ludzie blisko miodu");
    miod.ustawStan("Nie ma ludzi blisko miodu");
    miod.ustawStan("Ida ludzie");

    std::cout &lt;&lt; "Ilosc miodu: " &lt;&lt; miod.pobierzIlosc() &lt;&lt; std::endl;
    delete mis1;
    delete mis2;
    return 0;
}

Leave a Reply

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.

Related Post