Changes between Initial Version and Version 1 of ObserverHowto


Ignore:
Timestamp:
Aug 2, 2012, 12:23:07 PM (12 years ago)
Author:
ankele
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ObserverHowto

    v1 v1  
     1= Observer Howto =
     2
     3== Theory ==
     4
     5The ''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.
     6
     7== Implementation ==
     8
     9=== Creating an observable ===
     10
     11  * derive the observable class from {{{Observable}}}
     12  * create an enum type with one element for each type of change about to occur
     13  * surround any code that makes notify-worthy changes with {{{OBSERVE;}}} and {{{NOTIFY(channel);}}} with {{{channel}}} the appropriate enum constant
     14
     15For example:
     16
     17{{{
     18  class MyObservable : public Observable
     19  {
     20    ...
     21  public:
     22    enum NotificationType{ // should be public (the observer will want to use this type!)
     23      SomethingDone,
     24      OtherStuffDone
     25    };
     26    void doSomeChanges()
     27    {
     28      OBSERVE;
     29      ... // do the actual changes
     30      NOTIFY(SomethingDone); // send notifications to all observers
     31    }
     32  };
     33}}}
     34
     35=== Creating an observer ===
     36
     37  * derive the observer class from {{{Observer}}}
     38  * add a virtual member function
     39     {{{virtual void MyObserver::update(Observable *publisher);}}}
     40    to be called on changes
     41  * (''optionally'') add a virtual member function
     42     {{{virtual void MyObserver::recieveNotification(Observable *publisher, Notification_ptr notification);}}}
     43    to be called on changes with more information
     44  * add a virtual member function
     45     {{{virtual void MyObserver::subjectKilled(Observable *publisher);}}}
     46    to be called when the observable is deleted
     47  * signon...
     48
     49Simple example:
     50{{{
     51  class MyObserver : public Observer
     52  {
     53  public:
     54    MyObserver()
     55    {
     56      MyObservable *observable = ...;
     57      observable->signOn(this);
     58    }
     59    virtual ~MyObserver()
     60    {
     61      observable->signOff(this);
     62    }
     63    virtual void update(Observable *publisher)
     64    {
     65      // react to changes
     66    }
     67    virtual void subjectKilled(Observable *publisher){}
     68  };
     69}}}
     70
     71More complex example:
     72{{{
     73  class MyObserver : public Observer
     74  {
     75  public:
     76    MyObserver()
     77    {
     78      MyObservable *observable1 = ...;
     79      MyObservable *observable2 = ...;
     80      observable1->signOn(this); // receive all notifications
     81      observable2->signOn(this, MyObservable::SomethingChanged); select specific notifications
     82      observable2->signOn(this, MyObservable::OtherStuffChanged);
     83    }
     84    virtual ~MyObserver()
     85    {
     86      observable1->signOff(this);
     87      observable2->signOff(this);
     88    }
     89    virtual void update(Observable *publisher)
     90    {
     91      // react to any changes
     92    }
     93    virtual void recieveNotification(Observable *publisher, Notification_ptr notification)
     94    {
     95      if (notification->getChannelNo() == MyObservable::SomethingChanged){
     96        // react to specific notification
     97      }
     98    }
     99    virtual void subjectKilled(Observable *publisher){}
     100  };
     101}}}
     102
     103== Caveats ==
     104
     105Using {{{observableObject->signOff(this);}}} in the observer's destructor will cause a segfault in case the observable is deleted while the observer lives on.
     106
     107For rather short lived observables this has to be circumvented:
     108
     109{{{
     110  class MyObserver : public Observer
     111  {
     112    MyObservable *observable;
     113
     114    MyObserver()
     115    {
     116      observable = ...;
     117      observable->signOn(this);
     118    }
     119    virtual ~MyObserver()
     120    {
     121      if (observable) // only sign off if the observer still lives
     122        observable->signOff(this);
     123    }
     124    virtual void update(Observable *publisher)
     125    {
     126      // react to changes
     127    }
     128    virtual void subjectKilled(Observable *publisher)
     129    {
     130      observable = NULL; // don't sign off
     131    }
     132  };
     133}}}