监听者-观察者模式

     在C++模式设计中,常用的一种模式设计方法就是监听者-观察者模式。每个监听者对象都把自己理解的事件注册到一个中心事件处理注册库,接收到消息后,中心事件处理注册库会把该消息分发到每个监听者对象。

    下面是来自于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,可以通过fMessage0Received变量验证,它确实收到了消息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;
}

源码下载:

https://files.cnblogs.com/mikewolf2002/WatchListener.zip

posted on   迈克老狼2012  阅读(1736)  评论(0编辑  收藏  举报

编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程

导航

< 2012年10月 >
30 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 1 2 3
4 5 6 7 8 9 10
点击右上角即可分享
微信分享提示