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] (aktualna) 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: | ||