Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
ZveřejnilMatěj Müller
1
Observer Martin Dráb Návrhové vzory, 2015
2
Co to je? Definuje závislost 1:N mezi objekty Závislé objekty jsou informovány o změně stavu Konzistentní stav souboru objektů Vazba mezi objekty je velmi volná Vyšší znovupoužitelnost kódu Také známé jako publish-subscribe Hlavní protagonisté Observer je informován o změně stavu subjektu. Na subjektu jinak nezávislý. Subjekt o změnách svého stavu informuje observery, které se za tímto účelem zaregistrovaly. Poskytuje rozhraní na registrování a odregistrování observerů Registrovaných observerů může být libovolné množství O jednotlivých observerech neví nic
3
Rozhraní a třídy
4
Jak to (teoreticky) funguje
5
Vlastnosti Abstraktní vazba mezi subjektem a observerem Subjekt nezná konkrétní třídy observerů, pouze obecný interface Každý z aktérů může patřit do jiné vrstvy (nízkoúrovňové subjekty mohou informovat observery vyšší úrovně) Broadcast Subjekt jej provádí automaticky Je zodpovědnost konkrétního observeru, zda notifikaci o změně stavu subjektu bude ignorovat či ne Neznámá cena změny stavu subjektu I malá změna stavu subjektu může být drahá, pokud je zaregistrováno mnoho observerů, nebo je zpracování notifikace náročné
6
Učebnicový příklad class Subject { public: virtual ~Subject() { } virtual void attach(Observer *o) { obSet_.insert(o); } virtual void detach(Observer *o) { obSet_.remove(o); } virtual void notify() { for (auto o : obSet_) o->update(); } protected: Subject() { } private: std::set obSet_; }; class Observer { public: virtual ~Observer() { } virtual void update() = 0; protected: Observer() { } };
7
Učebnicový příklad II class Clock : public Subject { public: unsigned int getSeconds() { return timeInSeconds_ % 60; } unsigned int getMinutes() { return (timeInSeconds_ / 60) % 60; } unsigned int getHours() { return (timeInSeconds_ / 3600) % 24; } void tick() { ++timeInSeconds_; notify(); } private: unsigned int timeInSeconds_; }; class AnalogClock : public Observer { public: virtual void update() { // draw the clock } AnalogClock(Clock *aClock) : clock_(aClock) { clock_->attach(this); } private: Clock *clock_; }; class DigitalClock : public Observer { public: virtual void update() { // draw the clock } DigitalClock(Clock *aClock) : clock_(aClock) { clock_->attach(this); } private: Clock *clock_; };
8
Učebnicový příklad III int main() { Clock *timer = new Clock(); DigitalClock *dc = new DigitalClock(timer); AnalogClock *ac = new AnalogClock(timer); while (true) { Sleep(1000); timer->tick(); } return 0; }
9
Implementace Mapování subjektů na observery Každý subjekt si pamatuje své observery (seznam, jiná struktura) Globální datová struktura (hash. tabulka) mapující subjekty na obeservery Pozorování více než jednoho subjektu void Observer::Update(Subject *s); Kdy notifikovat observery? Provede subjekt po každé změně stavu Notifikace jsou automatické („nezapomenutelné“) Zbytečné notifikace při sekvenci malých změn stavu Provede klient poté, co dokončí změnu stavu subjektu Notifikace až po dokončení sekvence malých úprav Větší náchylnost k chybám
10
Implementace II Mazání subjektů Mazání subjektu zneplatní reference na něj uložené v jeho observerech Lze vyřešit speciálním druhem notifikace Rozumnější cílení notifikací Obrana proti nechtěnému broadcastu Observer při registraci specifikuje, jaké druhy notifikací (změn stavu subjektu) jej zajímají
11
Push a pull model Subjekt může v rámci notifikace poskytnout určité informace o změně svého stavu, čímž může observerům ušetřit práci. Push model Subjekt předává prakticky všechny informace v rámci notifikace (v parametrech metody update) Windows PS Notify Routines Pull model Subjekt v rámci notifikací nepředává žádné informace Je na observerech, aby si v rámci metody update zjistili, co se změnilo \Callback\SetSystemTime, Windows kernel
12
ChangeManager
13
Využití v praxi Windows (low-level) PS Notify Routines Callback objects (observer v C) Monitorování registru/FS... Listenery v Javě ….
14
Callback Objects (Windows) ExCreateCallback Získá odkaz na callback objekt, nebo vytvoří nový objekt ObDereferenceObject Odevzdání odkazu na callback objekt zpět systému ExRegisterCallback Subject::Attach ExUnregisterCallback Subject::Detach ExNotifyCallback Subject::Notify Příklady: \Callback\SetSystemTime \Callback\ProcessorAdd
15
PS Notify Routines (Windows) Opět pouze prostředky jazyka C => práce s callbacky Uživatel píše jen observera Vhodné obalit vlastním subjektem (počet registrovatelných callbacků je omezen (8-64?)) Registrace PsSetCreateProcessNotifyRoutine(_ProcessCallback, FALSE); Deregistrace PsSetCreateProcessNotifyRoutine(_ProcessCallback, TRUE); Notifikace (provádí systém) void _ProcessCallback(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create);
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.