Różnice między wybraną wersją a wersją aktualną.
Both sides previous revision Previous revision Next revision | Previous revision | ||
obserwator [2008/04/14 13:42] wojtek-j |
obserwator [2008/04/14 14:05] wojtek-j |
||
---|---|---|---|
Linia 1: | Linia 1: | ||
======Wzorzec Projektowy Obserwator====== | ======Wzorzec Projektowy Obserwator====== | ||
- | Wzorzec Obserwatora (ang. The Observer Pattern) jest wzorcem projektowym służącym do obserwowania stanu obiektu. Wzorzec ten jest pomyślany do rozwiązania sytuacji w której stan większej liczby obiektów (obserwatorów) zależy od stanu innego obiektu (obserwowanego) - pomaga zachować spójność między nimi. | + | Wzorzec Obserwatora (ang. The Observer Pattern) jest wzorcem projektowym służącym do obserwowania stanu obiektu. Wzorzec ten jest pomyślany do rozwiązania sytuacji w której stan większej liczby obiektów (obserwatorów) zależy od stanu innego obiektu (obserwowanego) - pomaga zachować spójność między nimi. W ogólnym przypadku działanie jego polega na rejestrowaniu przez obiekt obserwowany obiektów go obserwujących (Obserwatorów), a następnie po zmianie swojego stanu powiadomieniu wszystkich Obserwatorów o tym fakcie tak, aby każdy z nich mógł odpowiednio zaktualizować swój stan. Wzorzec jest szczególnie przydatny w przypadkach gdy rodzaj i ilość obserwatorów nie jest znana lub zmienna. |
=====Diagram UML===== | =====Diagram UML===== | ||
- | {{ observer:uml_1.jpg |}} | + | {{ observer:uml1.jpg |}} |
+ | =====Opis elementów wzorca===== | ||
+ | W skład wzorca wchodzą cztery elementy: | ||
+ | - **[[obserwator#Abstrakcyjny Obserwowany|Abstrakcyjny Obserwowany]]**: Klasa abstrakcyjna dostarczająca interfejs dla dodawania i usuwania obserwatorów, oraz powiadamiania o zmianie stanu wszystkich obserwatorów z listy. Zawiera: | ||
+ | * //dodaj//- dodaje obserwatora | ||
+ | * //usun//- usuwa obserwatora | ||
+ | * //powiadom//- powiadamia o zmianie wszystkich obserwatorow z listy poprzez wołanie metody odswież dla każdego z nich | ||
+ | - **[[obserwator#Obserwowany Konkretny|Obserwowany Konkretny]]**: Klasa zwraca swój wewnętrzny stan, który jest obiektem zainteresowania obserwatorów. Powiadamia także swoich obserwatorów na wypadek zmiany swojego stanu. Zawiera: | ||
+ | * //podaj_stan// - zwraca aktualny stan obiektu | ||
+ | - **[[obserwator#Abstrakcyjny Obserwator|Abstrakcyjny Obserwator]]**: Klasa abstrakcyjna dostarczająca interfejs dla powiadamiania dla wszystkich obserwatorów. Zawiera: | ||
+ | * //odswiez// - abstrakcyjna metoda która ma być nadpisana przez konkretnego obserwatora | ||
+ | - **[[obserwator#Obserwator konkretny|Obserwator konkretny]]**: Klasa pozostaję w związku z obiektem obserwowanym (ObserwowanyKonkretny) aby otrzymać/pobrać jego stan w wypadku powiadomienia o zmienie. Zawiera: | ||
+ | * //odswiez// - podczas wołania tej metody (która nadpisuje metode abstrakcyjną w klasie bazowej), konkretny obserwator woła podaj_stan dla obiektu obserwowanego aby zaktualizować informację o nim | ||
=====Kod w C++===== | =====Kod w C++===== | ||
- | * **Abstrakcyjny Obserwowany** | + | ====Abstrakcyjny Obserwowany==== |
<code cpp> | <code cpp> | ||
class Obserwowany { | class Obserwowany { | ||
public: | public: | ||
- | /* dodaj obserwatora o do listy obserwatorow */ | + | /** |
+ | * dodaje obserwatora o do listy obserwatorow | ||
+ | */ | ||
void dodaj(Obserwator* o) { | void dodaj(Obserwator* o) { | ||
+ | //dodaj obserwatora o do listy obserwatorow | ||
} | } | ||
+ | /** | ||
+ | * powiadamia kazdego obserwatora o zmianie stanu | ||
+ | */ | ||
void powiadom(){ | void powiadom(){ | ||
- | /* dla każdego o w obserwatorzy wywołaj o->odswiez() */ | + | //dla każdego o w obserwatorzy wywołaj o->odswiez() |
} | } | ||
- | virtual ~Obserwowany() = 0; | + | /** |
+ | * abstrakcyjny destruktor | ||
+ | */ | ||
+ | virtual ~Obserwowany() { | ||
+ | ; | ||
+ | }; | ||
private: | private: | ||
- | std::vector<Obserwator*> obserwatorzy; | + | /** |
+ | * lista obserwatorow | ||
+ | */ | ||
+ | std::vector<Obserwator*> obserwatorzy_; | ||
}; | }; | ||
- | Subject::~Subject(){} | ||
</code> | </code> | ||
+ | ====Obserwowany konkretny==== | ||
<code cpp> | <code cpp> | ||
- | //Obserwowany konkretny | ||
class ObserwowanyKonkretny : public Obserwowany { | class ObserwowanyKonkretny : public Obserwowany { | ||
public: | public: | ||
- | void podaj_stan(StanObserwowanego* stan) { | + | /** |
- | /* podaj stan, np. poprzez odpowiednia struktore StanObserwowanego */ | + | * podaje stan obiektu obserwowanego |
+ | */ | ||
+ | StanObserwowanego podaj_stan() { | ||
+ | //zwroc stan_ | ||
} | } | ||
+ | private: | ||
+ | /** | ||
+ | * opisuje stan obiektu obserwowanego | ||
+ | */ | ||
+ | StanObserwowanego* stan_; | ||
}; | }; | ||
- | //Abstrakcyjny Obserwator | + | </code> |
+ | ====Abstrakcyjny Obserwator==== | ||
+ | <code cpp> | ||
class Obserwator { | class Obserwator { | ||
public: | public: | ||
+ | /** | ||
+ | * powiadamia obserwatora o zajsciu zmiany stanu w obiekcie obserwowanym | ||
+ | */ | ||
virtual void odswiez() = 0; | virtual void odswiez() = 0; | ||
- | virtual ~Obserwator(){} | + | /** |
+ | * abstrakcyjny destruktor | ||
+ | */ | ||
+ | virtual ~Obserwator() { | ||
+ | ; | ||
+ | } | ||
}; | }; | ||
- | //Obserwator konkretny | + | </code> |
+ | ====Obserwator konkretny==== | ||
+ | <code cpp> | ||
class ObserwatorKonkretny : public Obserwator { | class ObserwatorKonkretny : public Obserwator { | ||
public: | public: | ||
+ | /** | ||
+ | * powiadamia obserwatora o zajsciu zmiany stanu w obiekcie obserwowanym | ||
+ | */ | ||
void odswiez() { | void odswiez() { | ||
- | /* uzyskaj aktualny stan obserwowanego */ | + | /* uzyskaj aktualny stan obiektu obserwowanego */ |
} | } | ||
}; | }; | ||
</code> | </code> | ||
- | =====Opis elementów wzorca===== | ||
- | W skład wzorca wchodzą cztery elementy: | ||
- | - **Obserwowany**: Klasa abstrakcyjna dostarczająca interfejs dla dodawania i usuwania obserwatorów, oraz powiadamiania o zmianie stanu wszystkich obserwatorów z listy. Zawiera: | ||
- | * //dodaj//- dodaje obserwatora | ||
- | * //usun//- usuwa obserwatora | ||
- | * //powiadom//- powiadamia o zmianie wszystkich obserwatorow z listy poprzez wołanie metody odswież dla każdego z nich | ||
- | - **Obserwowany Konkretny**: Klasa zwraca swój wewnętrzny stan, który jest obiektem zainteresowania obserwatorów. Powiadamia także swoich obserwatorów na wypadek zmiany swojego stanu. Zawiera: | ||
- | * //podaj_stan// - zwraca aktualny stan obiektu | ||
- | - **Obserwator**: Klasa abstrakcyjna dostarczająca interfejs dla powiadamiania dla wszystkich obserwatorów. Zawiera: | ||
- | * //odswiez// - abstrakcyjna metoda która ma być nadpisana przez konkretnego obserwatora | ||
- | - **Obserwator konkretny**: Klasa pozostaję w związku z obiektem obserwowanym (ObserwowanyKonkretny) aby otrzymać/pobrać jego stan w wypadku powiadomienia o zmienie. Zawiera: | ||
- | * //odswiez// - podczas wołania tej metody (która nadpisuje metode abstrakcyjną w klasie bazowej), konkretny obserwator woła podaj_stan dla obiektu obserwowanego aby zaktualizować informację o nim | ||
=====Typowe użycie===== | =====Typowe użycie===== | ||
Dla przykładu weźmy dwa obiekty **A** oraz **B**, przy czym stan obiektu **A** jest zależny od stanu obiektu **B**, czyli może się zdarzyć że po zmianie stanu obiektu **B** obiekt **A** również powinien zmienić swój stan. W tym ogólnym (i prostym) przypadku można pokusić się o bezpośrednią interakcje pomiędzy obiektami poprzez utrzymanie w jednym z nich wskaźnika lub referencji na drugi. Sytuacja jednak komplikuje się kiedy: | Dla przykładu weźmy dwa obiekty **A** oraz **B**, przy czym stan obiektu **A** jest zależny od stanu obiektu **B**, czyli może się zdarzyć że po zmianie stanu obiektu **B** obiekt **A** również powinien zmienić swój stan. W tym ogólnym (i prostym) przypadku można pokusić się o bezpośrednią interakcje pomiędzy obiektami poprzez utrzymanie w jednym z nich wskaźnika lub referencji na drugi. Sytuacja jednak komplikuje się kiedy: |