Online Book Reader

Home Category

Professional C__ - Marc Gregoire [493]

By Root 1569 0
inMessage)

{

switch (inMessage) {

case kMessageDelete:

handleDelete();

break;

default:

{

stringstream ss;

ss << __func__ << ": Unrecognized message received: " << inMessage;

throw invalid_argument(ss.str());

}

}

}

When the event-handling portion of the program or framework receives a message, it finds the corresponding shape and calls handleMessage(). Through polymorphism, the subclass’s version of handleMessage() is called. This gives the leaf node first crack at handling the message. If it doesn’t know how to handle it, it passes it up to its superclass, which gets the next chance. In this example, the final recipient of the message throws an exception if it is unable to handle the event. You could also have your handleMessage() method return a boolean indicating success or failure.

Note that while event chains usually correlate with the class hierarchy, they do not have to. In the preceding example, the Square class could have just as easily passed the message to an entirely different object. The chained approach is flexible and has a very appealing structure for object-oriented hierarchies. The downside is that it requires diligence on the part of the programmer. If you forget to chain up to the superclass from a subclass, events will effectively get lost. Worse, if you chain to the wrong class, you could end up in an infinite loop!

Using a Chain of Responsibility

For a chain of responsibility to respond to events, there must be another class that dispatches the events to the correct object. Because this task varies greatly by framework or platform, the following example shows pseudocode for handling a mouse down event, in lieu of platform-specific C++ code:

MouseLocation loc = getClickLocation();

Shape* clickedShape = findShapeAtLocation(loc);

if (clickedShape)

clickedShape->handleMessage(kMessageMouseDown);

THE OBSERVER PATTERN


The other common model for event handling is known as observer, listener messaging, or publish and subscribe. This is a more prescriptive model that is often less error-prone than message chains. With the publish and subscribe technique, individual objects register the events they are able to understand with a central event handling registry. When an event is received, it is transmitted to the list of subscribed objects.

Example: Event Handling

Just as with the earlier chain of responsibility pattern, observers are often used to handle events. The main difference between the two patterns is that the chain of responsibility works best for logical hierarchies where you need to find the correct class to handle the event. Observers work best when events can be handled by multiple objects, or are unrelated to a hierarchy.

Implementation of an Observer

First, a Listener mix-in class is defined. Any object that wants to subscribe to one or more events should inherit from this mix-in class:

class Listener

{

public:

virtual void handleMessage(int inMessage) = 0;

};

Code snippet from Observer\Listener.h

The definition of a simple event registry class is shown next. It allows any object that extends the mix-in class Listener to subscribe to one or more events. It maintains a directory of Listeners and their corresponding events. It also contains a method for the program to call when an event is received, which will dispense the event to all subscribed Listeners.

To simplify this example, a few assumptions are made. These assumptions are not necessarily going to be valid in all contexts. To focus the example on demonstrating the observer pattern, the event registry just uses static methods and a static map, meaning there is only one map during the run time of the program. If you need multiple separate event registries, you’ll have to adapt the EventRegistry class. Support for unregistering listeners is also not included. Normally, the destructor of a listener may want to unregister all subscriptions for that object. The given implementation also allows an object to register itself twice, which may be undesirable depending on your use case. You might also need to

Return Main Page Previous Page Next Page

®Online Book Reader