• 监听者观察者模式


         在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

  • 相关阅读:
    PHP获取汉字拼音首字母
    记录,待总结5
    HDU2833 WuKong Floyd
    搜索
    记录,待总结4
    HDU3350 #define is unsafe 栈的应用
    指针与引用的混合使用总结
    多源最短路径 Floyd
    引用总结
    函数返回值总结
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2728279.html
Copyright © 2020-2023  润新知