views:

95

answers:

2

First of all, I know there are excellent implementations (Qt, Boost, cpp-event, etc.), but I ask the question because I want to know how it works !

If I understand correctly, the "event system" uses the Observer pattern : some objects are observing, waiting for something to happen... and some others send signals. All right.

So, let's say I've got my observer class, with this kind of thing :

void Observer::getNotified() 
{
    // Do stuff
}

My question is : how to manage dynamically what kind of stuff should be done ? I've seen a lot of people saying specifically not to use functions pointers. For my current need, I can do a switch statement, a enum type, and select different behaviors, but that's not very satisfying. So, if it's not functions pointers, how is it done ?

+1  A: 

See this rather excellent article from Pete Goodliffe, which routes to different methods depending on the event type being notified.

If you need to choose actions within a single event type, then typically your code would choose depending on the data passed in the notification.

Seb Rose
Interesting! +1
Klaim
Indeed, quite interesting. I'll start with that, thanks !
Raveline
+3  A: 

There is a lot of different implementations possible (whatever the language), but the abstract idea is :

  1. have an event type identifier to know wich events have been fired by the observed object (it can be whatever works);
  2. have a list of observers (or several, one by event type?) registered in the registered objects - that suppose that the observers are functors (function pointer or object that act like a function) or are objects with a known interface (with a virtual method to call ion event fired);
  3. when an event is fired (by calling a function on the observed object) we just go through the list of observers registered for the event's type and pass the event information (id plus maybe data ) to the observer to be processed;

Here is a simplist implementation :

enum EventType
{
   Event_A,
   Event_B,
};

class Observer // for this example i'll suppose observer inherits this class
{
    virtual void catchEvent( EventType e ) = 0; // for sake of the example I just need the event type, not the data, but it's often required

    virtual ~Observer(){}; // virtual base classes require this to work fine.
};

class Observed
{
      typedef std::vector<Observer*> ObserverList; 
      typedef std::map< EventType, ObserverList > ObserversTable;
      ObserversTable m_observers; // we have observers for each event type

public:

     void addObserver( Observer& observer, EventType eType ) 
     { m_observers[ eType ].push_back( observer ); } // this is simplist, to say the least...

     void sendEvent( EventType event ) // here we send the event, it will be catched by observers
     { // note : often this type of system is "buffered", but here we will process it immediatly as it's a simple example

        ObserverList& observers = m_observers[ event ];  
        for ( ObserverList::iterator it = observers.begin(); it != observers.end(); ++it )
        {
              Observer* observer = *it;
              observer->catchEvent( event ); // here an observer receive the event
        }

     }
};

It's really a basic example but that might help you understand the idea.

Klaim
Thank you : it doesn't quite understand my question, but it'll be very helpful too.
Raveline
It don't answer directly because as I said : There is a lot of different implementations possible (whatever the language)I've implemented tons of radically different way to do it in C++ only (and other variants in other languages) and it's hard to use a specific implementation for everything.Or maybe I didn't understood the exact point of your question? :)
Klaim
@Raveline: have another look, it does answer your question: instead of using function pointers, inherit from an interface (Observer). Then it shows how to manage dynamically what kind of stuff should be done.
stefaanv
@stefaanv : You're right, it does ! My mistake, I didn't grab the whole idea when I looked at the code.@Klaim : You got it, I'm sorry.
Raveline