リスナー-オブザーバモード

8073 ワード

C++モード設計においてよく用いられるモード設計方法の1つは,傍受者−観察者モードである.各リスナー・オブジェクトは、自分が理解したイベントを1つのセンター・イベント処理レジストリに登録し、メッセージを受信すると、センター・イベント処理レジストリはそのメッセージを各リスナー・オブジェクトに配布します.
次に、c++profressionalからのコードを示します.
まず、リスナークラスです.
Listener.hとListener.cpp、これはリスナーベースクラスで、メッセージ処理の純粋な虚関数を定義し、コードは以下の通りです.
#pragma once

class Listener
{
public:
Listener(void);
~Listener(void);
virtual void handleMessage(int inMessage) = 0;
};

 
#include "Listener.h"

Listener::Listener(void)
{
}

Listener::~Listener(void)
{
}

派生するリスニングクラスはTestListenerであり、このクラスは以下のように実現される.
TestListener.h
#pragma once
#include "listener.h"
#include "EventRegistry.h"

class TestListener :
public Listener
{
public:
TestListener(void);
~TestListener(void);

void handleMessage(int inMessage);
bool fMessage0Received;
bool fUnknownMessageReceived;
};

TestListener.cpp,このクラスはコンストラクション関数において,自己およびメッセージ0をセンタイベント処理ライブラリに登録する.
#include "TestListener.h"

TestListener::TestListener(void)
{
fMessage0Received = false;
fUnknownMessageReceived = false;
// 0
EventRegistry::registerListener(0, this);
}

TestListener::~TestListener(void)
{
}

void TestListener::handleMessage(int inMessage)
{
switch (inMessage)
{
case 0:
fMessage0Received = true;
break;
default:
fUnknownMessageReceived = true;
break;
}
}

次に、イベント登録クラスの実装を示します.このクラスにリスナークラスを追加するたびに、クラスの参照がmapに追加されます.このクラスの実装コードは次のとおりです.
EventRegistry.hとEventRegistry.cpp
#pragma once
#include <vector>
#include <map>
#include <iostream>
#include "Listener.h"
using namespace std;

class EventRegistry
{
public:
EventRegistry(void);
~EventRegistry(void);
static void registerListener(int inMessage, Listener* inListener);
static void handleMessage(int inMessage);
protected:
static map<int, vector< Listener*> > sListenerMap;
};

 
#include "EventRegistry.h"

// map
map<int, vector< Listener*> > EventRegistry::sListenerMap;
EventRegistry::EventRegistry(void)
{
}

EventRegistry::~EventRegistry(void)
{
}

void EventRegistry::registerListener(int inMessage, Listener* inListener)
{
//
sListenerMap[inMessage].push_back(inListener);
}
void EventRegistry::handleMessage(int inMessage)
{
// ,
if (sListenerMap.find(inMessage) == sListenerMap.end()) return;
for (int i = 0; i < sListenerMap[inMessage].size(); i++) {
sListenerMap[inMessage].at(i)->handleMessage(inMessage);
}
}

main関数では、センタ登録クラスはメッセージ0,1,2を受信し、登録されたリスニングクラスを配布し、TestListenerはメッセージ0を登録し、fMessage 0 Received変数によって検証することができ、メッセージ0を確実に受信した.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "EventRegistry.h"
#include "Listener.h"
#include "TestListener.h"

using namespace std;

int main(int argc, char* argv[])
{

TestListener tt ;
EventRegistry::handleMessage(0);
EventRegistry::handleMessage(1);
EventRegistry::handleMessage(2);
if (!tt.fMessage0Received) {
cout << "TEST FAILED: Message 0 was not received" << endl;
} else if (tt.fUnknownMessageReceived) {
cout << "TEST FAILED: TestListener received unknown message" << endl;
} else {
cout << "TEST PASSED" << endl;
}

return 0;
}

ソースのダウンロード:
http://files.cnblogs.com/mikewolf2002/WatchListener.zip