Online Book Reader

Home Category

Professional C__ - Marc Gregoire [494]

By Root 1352 0
register objects with an implied ordering (for example, Z-axis for graphical objects) in which events are processed; in the following example, there is no implied ordering, so an std::map is used, which imposes its own order on event handling. Note that the model has many variants depending on the needs of the design. Thus, you should read this code for the overall structure, and not think of it as an exact model that is universally applicable in all circumstances.

#include "Listener.h"

#include

#include

class EventRegistry

{

public:

static void registerListener(int inMessage, Listener* inListener);

static void handleMessage(int inMessage);

protected:

static std::map> sListenerMap;

};

Code snippet from Observer\EventRegistry.h

The implementation of the EventRegistry class follows. When a new Listener is registered, it is added to the vector of Listeners stored in the listener map for the given event. When an event is received, the registry simply retrieves the vector and passes the event to each Listener:

// Define the static map.

map> EventRegistry::sListenerMap;

void EventRegistry::registerListener(int inMessage, Listener* inListener)

{

// Chapter 12 explains std::map. Note that if you specify a key

// using [] to access it, and there is not yet an entry in the map for

// that key, a new entry is created.

sListenerMap[inMessage].push_back(inListener);

}

void EventRegistry::handleMessage(int inMessage)

{

// Check to see if the message has *any* listeners. This check is required

// because otherwise, accessing sListenerMap[inMessage] would create

// a new entry when it's not yet in the map. See Chapter 12.

if (sListenerMap.find(inMessage) == sListenerMap.end())

return;

for (auto iter = sListenerMap[inMessage].begin();

iter != sListenerMap[inMessage].end(); ++iter) {

(*iter)->handleMessage(inMessage);

}

}

Code snippet from Observer\EventRegistry.cpp

Using an Observer

Following is a very simple unit test that demonstrates how to use the publish and subscribe technique. The class TestListener subscribes to message 0 in its constructor. Subscribing to a message in a constructor is a common pattern for objects that are Listeners. The class contains two flags that keep track of whether message 0 was successfully received, and whether any unknown messages were received. If message 0 was received and no unknowns were received, the test passes.

class TestListener : public Listener

{

public:

TestListener();

void handleMessage(int inMessage);

bool bMessage0Received;

bool bUnknownMessageReceived;

};

Code snippet from Observer\TestListener.h

TestListener::TestListener() :

bMessage0Received(false),

bUnknownMessageReceived(false)

{

// Subscribe to event 0.

EventRegistry::registerListener(0, this);

}

void TestListener::handleMessage(int inMessage)

{

switch (inMessage) {

case 0:

bMessage0Received = true;

break;

default:

bUnknownMessageReceived = true;

break;

}

}

Code snippet from Observer\TestListener.cpp

int main()

{

TestListener tl;

EventRegistry::handleMessage(0);

EventRegistry::handleMessage(1);

EventRegistry::handleMessage(2);

if (!tl.bMessage0Received) {

cout << "TEST FAILED: Message 0 was not received" << endl;

} else if (tl.bUnknownMessageReceived) {

cout << "TEST FAILED: TestListener received unknown message" << endl;

} else {

cout << "TEST PASSED" << endl;

}

return 0;

}

Code snippet from Observer\TestObserver.cpp

Of course, an actual implementation in your program would vary from the implementation shown here based on the services provided by the environment and your individual needs.

SUMMARY


This chapter has given you just a taste of how patterns can help you organize object-oriented concepts into high-level designs. There is a seemingly infinite supply of design patterns cataloged and discussed on the Portland Pattern Repository Wiki at www.c2.com. It’s easy to get carried away and spend all your time trying to find the specific pattern that applies to your task.

Return Main Page Previous Page Next Page

®Online Book Reader