= Observer Howto = == Theory == The ''Observer'' pattern is a way of implementing a one-to-many dependency. There usually is one observable object automatically notifying multiple observer objects of its changes. For doing so the observer keeps a list of its observables. The observables in turn have to sign on to the observer's list. == Implementation == === Creating an observable === * derive the observable class from {{{Observable}}} * create an enum type with one element for each type of change about to occur * surround any code that makes notify-worthy changes with {{{OBSERVE;}}} and {{{NOTIFY(channel);}}} with {{{channel}}} the appropriate enum constant For example: {{{ class MyObservable : public Observable { ... public: enum NotificationType{ // should be public (the observer will want to use this type!) SomethingDone, OtherStuffDone }; void doSomeChanges() { OBSERVE; ... // do the actual changes NOTIFY(SomethingDone); // send notifications to all observers } }; }}} === Creating an observer === * derive the observer class from {{{Observer}}} * add a virtual member function {{{virtual void MyObserver::update(Observable *publisher);}}} to be called on changes * (''optionally'') add a virtual member function {{{virtual void MyObserver::recieveNotification(Observable *publisher, Notification_ptr notification);}}} to be called on changes with more information * add a virtual member function {{{virtual void MyObserver::subjectKilled(Observable *publisher);}}} to be called when the observable is deleted * signon... Simple example: {{{ class MyObserver : public Observer { public: MyObserver() { MyObservable *observable = ...; observable->signOn(this); } virtual ~MyObserver() { observable->signOff(this); } virtual void update(Observable *publisher) { // react to changes } virtual void subjectKilled(Observable *publisher){} }; }}} More complex example: {{{ class MyObserver : public Observer { public: MyObserver() { MyObservable *observable1 = ...; MyObservable *observable2 = ...; observable1->signOn(this); // receive all notifications observable2->signOn(this, MyObservable::SomethingChanged); select specific notifications observable2->signOn(this, MyObservable::OtherStuffChanged); } virtual ~MyObserver() { observable1->signOff(this); observable2->signOff(this); } virtual void update(Observable *publisher) { // react to any changes } virtual void recieveNotification(Observable *publisher, Notification_ptr notification) { if (notification->getChannelNo() == MyObservable::SomethingChanged){ // react to specific notification } } virtual void subjectKilled(Observable *publisher){} }; }}} == Caveats == Using {{{observableObject->signOff(this);}}} in the observer's destructor will cause a segfault in case the observable is deleted while the observer lives on. For rather short lived observables this has to be circumvented: {{{ class MyObserver : public Observer { MyObservable *observable; MyObserver() { observable = ...; observable->signOn(this); } virtual ~MyObserver() { if (observable) // only sign off if the observer still lives observable->signOff(this); } virtual void update(Observable *publisher) { // react to changes } virtual void subjectKilled(Observable *publisher) { observable = NULL; // don't sign off } }; }}}