Wzorzec Obserwator
26 sierpnia, 2022 23:14 | by Agnieszka | Posted in Wzorce projektowe

Obserwator to czynnościowy (behawioralny) wzorzec projektowy, który pozwala zdefiniować mechanizm subskrypcji w celu powiadomienia wielu obiektów o zdarzeniach dziejących się w obserwowanym obiekcie. Definiuje pomiędzy obiektami relację jeden-do-wielu w taki sposób, że kiedy wybrany obiekt zmienia swój stan, to wszystkie jego obiekty zależne zostaną o tym poinformowane i automatycznie zaktualizowane.
Obserwator może być implementowany na kilka różnych sposobów jednak większość z nich obraca się dookoła tworzenia osobnych klas, posiadających interfejsy Podmiot(Publisher) oraz Obserwator(Subscriber). Podmiot rozsyła zdarzenia interesujące inne obiekty, posiada infrastrukturę umożliwiającą subskrybowanie zdarzeń lub przerwanie subskrypcji. Gdy nastąpi nowe zdarzenie nadawca wywołuje metody powiadamiania zadeklarowane w interfejsach. Interfejs subskrybenta w większości przypadków składa się z jednej metody „aktualizuj”.
Dobrym przykładem do zaprezentowania tego wzorca jest subskrypcja kanału platformy Youtube.
Każdy Youtuber może mieć wielu subskrybentów na swoim kanale. Subskrybent, jeśli podoba mu się dany kanał może zacząć go obserwować, a jeśli straci zainteresowanie może w każdej chwili przestać. W przypadku naszego wzorca możemy myśleć o właścicielu kanału na Youtube jako Podmiocie, natomiast o subskrybujących go ludziach jako Obserwatorach.
Spójrzmy najpierw na rozwiązanie bez wzorca Obserwator
W powyższym rozwiązaniu napotykamy na problem, gdy pojawi się więcej subskrybentów danego kanału i każdego z nich trzeba będzie osobno informować o tym, że został dodany nowy film. Przejdźmy zatem do zastosowania wzorca w danym przykładzie. Rozpocznijmy od utworzenia klasy Subject która będzie umożliwiała dodanie, usunięcie oraz powiadomienie wszystkich obserwatorów.
Tworzymy interfejs dla Obserwatora
Następnie tworzymy klasę Youtuber, w której przesłaniamy wszystkie metody z Subject.
Klasa Subscriber implementująca interfejs Observer
Klasa Main oraz rezultat wywołania
Jak widać, po dodaniu nowego filmu, każdy z subskrybentów należący do listy został o nim poinformowany. Jeśli, któryś zrezygnuje z subskrypcji kanału, przestanie być uwzględniany w powiadomieniach.
Zastosowanie:
– gdy zmiany stanu jednego obiektu mogą wymagać zmiany w innych obiektach, a konkretny zestaw obiektów nie jest zawczasu znany lub ulega zmianom dynamicznie
– klasy graficzne interfejsu użytkownika (np. użytkownik może podpiąć własny kod pod stworzone własne klasy przycisków)
– każdy obiekt implementujący interfejs powiadomień otrzymuje powiadomienia o zdarzeniach w obiekcie publikującym
– gdy jakieś obiekty w aplikacji muszą obserwować inne, ale tylko przez jakiś czas lub w niektórych przypadkach
– lista obserwatorów jest dynamiczna, więc mogą oni zapisać się lub wypisać z listy kiedy chcą
Zalety:
– prosta implementacja, elastyczności
– brak ścisłej zależności między obserwatorami a obiektem między obserwatorami a obiektem obserwowanym, można rozwijać funkcjonalności
– zasada otwarte na rozbudowę /zamknięte na modyfikacje – można wprowadzać do programu nowe klasy obserwujące bez konieczności zmieniania kodu publikującego
Wady:
– brak możliwości wpływu na kolejność powiadamiania obserwatorów o zmianie stanu obiektu