#include <Observable.h>
Inheritance diagram for ZThread::Observable::
Public Methods | |
Observable () | |
Observable (LOCK *) | |
virtual | ~Observable () throw () |
virtual void | subscribe (T *) |
virtual void | unsubscribe (T *) |
void | notify () const |
template<class U> void | notify (const U &u) const |
template<class U, class V> void | notify (const U *u, const V &v) const |
The template creates the subject of the observer pattern to which listener objects of type 'T' can subscribe to. The listener objects are notified of each event as the notify() methods of the Observable object are invoked
The only requirement is that the listener object must implement the correct notify methods. So if you are using a parameterless notify() method on the Observer - the you need only implement notify() on the listener class. If you use a parameterized notify method, then you need implement the correct type method.
This means if you are calling notify(int) on the observer, then the listener class needs to implement the notify(int) method. These listener notify methods should be public
You need only to implement the notify function you use. This template includes three types of notify() methods, but if you don't use them all the compiler will ignore the unused portions of the template quietly.
The nice thing about this template is that is very flexible.
Consider a case where you have several type of log events, and you have an object that is interested in all of these event types - but will not necessarily take the take action for each. It might just be easier in general to implement a class with the different notify functions on them directly rather than creating several virtual base classes for each type and inheriting from them all. Of you may want to define a single virtual base class that implements all three of the needed notify() functions and maintain a strongly type system. Its up to the programmer how to define his listener classes no inheritance is forced here unless the programmer wishes to impose it, and no one is forced to use implicitly defined notify() methods either.
Observer<ListenerType> O; ListenerType L; O.subscribe(&L); O.notify( int(9) ); // Basic example O.notify( "Hello" ); // Or O.notify( LogMessage("Its OK") ); // More useful example O.notify( LogCritical("Error!") ); }
The ListenerType can be implemented as (Assuming LogMessage & LogCritical are valid classes)
// Weakly typed listener // just implements the notify methods that are implicitly defined // in the template class ListenerType { public: void notify(LogMessage); // These are function signatures for void notify(LogCritical); // simplicity sake }; // Strongly typed listener // The base just implements the notify methods that are implicitly defined // in the template, but forced some class to derive from this. The programmer // will need to realize what functions the observer will need to call to // define the abstract base correctly. class ListenerBaseType { public: virtual ~ListenerBaseType() {} virtual void notify(LogMessage) = 0; virtual void notify(LogCritical) = 0; }; class ListenerImpl : public ListenerBaseType { public: virtual void notify(LogMessage); virtual void notify(LogCritical); };
|
Create a new Observable object that owns its own Lockable object (which is used to manipulate its data) |
|
Create a new Observable object that shares it Lockable object (which is used to manipulate its data)
|
|
Destroy this Observable |
|
Distribute an event of type U to all subscribed objects, via their double parameter notify function
|
|
Distribute an event of type U to all subscribed objects, via their single parameter notify function
|
|
Distribute an event of type U to all subscribed objects, via their no-parameter notify function |
|
Subscribe to an observer
|
|
Unsubscribe from an observer
|