> 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.