c++实现消息发布/订阅机制例子(成员函数被其他类掉调用)

简单的消息发布订阅机制

以下是一个简单的使用 C++ 实现发布 / 订阅机制的示例代码。这个示例包含一个简单的事件系统,其中有发布者(Publisher)和订阅者(Subscriber)。

以下代码需要C++11以上支持

这个同时也是:成员函数被其他类掉调用的例子

#include <iostream>
#include <vector>
#include <functional>

// 事件参数结构体,可以根据实际需求修改
struct EventData {
    int value;
};

// 事件处理函数类型定义
using EventHandler = std::function<void(const EventData&)>;

// 发布者类
class Publisher {
public:
    void publish(const EventData& data) {
        for (const auto& handler : subscribers) {
            handler(data);
        }
    }

    void subscribe(EventHandler handler) {
        subscribers.push_back(handler);
    }

private:
    std::vector<EventHandler> subscribers;
};

// 订阅者类示例
class Subscriber {
public:
    Subscriber(const std::string& name) : name(name) {}

    void onEvent(const EventData& data) {
        std::cout << name << " received event with value: " << data.value << std::endl;
    }

private:
    std::string name;
};

int main()
{
    Publisher publisher;

    Subscriber sub1("Subscriber 1");
    Subscriber sub2("Subscriber 2");

    // 订阅者注册事件处理函数,这里将sub1的onEvent成员函数,传入到publisher的容器中,被后续publish触发调用。
    publisher.subscribe(std::bind(&Subscriber::onEvent, sub1, std::placeholders::_1));
    publisher.subscribe(std::bind(&Subscriber::onEvent, sub2, std::placeholders::_1));

    EventData event = { 42 };
    publisher.publish(event);

    EventData event2 = { 43 };
    publisher.publish(event2);

    return 0;
}
输出结果:
Subscriber 1 received event with value: 42
Subscriber 2 received event with value: 42
Subscriber 1 received event with value: 43
Subscriber 2 received event with value: 43

 

在这个示例中:
  1. Publisher
    • 有一个publish方法,用于遍历所有订阅者的事件处理函数,并调用它们,将事件数据传递给每个订阅者。
    • 有一个subscribe方法,用于将订阅者的事件处理函数添加到subscribers向量中。
  2. Subscriber
    • 每个订阅者有一个onEvent方法,这个方法定义了订阅者如何处理接收到的事件。在main函数中,通过std::bindSubscriberonEvent方法绑定到Publishersubscribe方法上,从而注册为事件处理函数。
  3. main函数中:
    • 创建了一个Publisher对象和两个Subscriber对象。
    • 两个Subscriber对象分别订阅了Publisher发布的事件。
    • 然后创建一个EventData对象,并通过Publisherpublish方法发布这个事件,此时所有订阅者都会接收到这个事件并进行相应的处理。

注意,这是一个非常基础的发布 / 订阅机制示例,在实际应用中,可能需要更多的功能,如事件类型的区分、动态订阅 / 取消订阅、多线程安全性等。

注意,这里的 Publisher 其实应改成 EventBus ,更能体现消息管理与订阅的解耦。

============================================升级扩展===================================================

添加事件过滤功能

注意:这里为了将原来的消息订阅机制与观察者模式做强烈的区分,将Publisher类改成EventBus类(消息管理总线) 

以下代码需要C++17以上支持

#include <iostream>
#include <vector>
#include <functional>
#include<map>
#include<unordered_map>

// 事件参数结构体,可以根据实际需求修改
struct EventData {
    int value;                  //具体的消息,可扩展
    std::string type;           //消息类型,目前用字符串表示
};

// 事件处理函数类型定义
using EventHandler = std::function<void(const EventData&)>;

//// 事件总线类,独立的公共消息通道
class EventBus {
private:
    // 使用vector存储事件处理函数及其过滤器
    std::vector<std::pair<EventHandler, std::vector<std::string>>> handlersAndFilters;
public:
    int subscribe(EventHandler handler, const std::vector<std::string>& filter = {}) {
        handlersAndFilters.push_back({ handler, filter });
        return handlersAndFilters.size() - 1;
    }

    void publish(const EventData& data) {
        for (size_t i = 0; i < handlersAndFilters.size(); ++i) {
            //基于C++17 的结构化绑定,给handler和filter使用handlersAndFilters[i]里面的pair进行赋值操作
            const auto& [handler, filter] = handlersAndFilters[i];
            if (filter.empty()) {
                handler(data);
            }
            else {
                for (const auto& type : filter) {
                    if (type == data.type) {
                        handler(data);
                        break;
                    }
                }
            }
        }
    }
};

// 订阅者类示例
class Subscriber {
public:
    Subscriber(const std::string& name) : name(name) {}

    void onEvent(const EventData& data) {
        std::cout << name << " received event with value: " << data.value << " and type: " << data.type << std::endl;
    }

private:
    std::string name;
};

int main()
{
    EventBus eventBus;

    Subscriber sub1("Subscriber 1");
    Subscriber sub2("Subscriber 2");

    // 订阅者1只订阅类型为"type1"(消息类型)的事件 
    eventBus.subscribe(std::bind(&Subscriber::onEvent, sub1, std::placeholders::_1), { "type1" });
    // 订阅者2订阅所有事件(没有设置过滤器)
    eventBus.subscribe(std::bind(&Subscriber::onEvent, sub2, std::placeholders::_1));

    EventData event1 = { 42, "type1" };//消息类型为"type1"的事件,消息内容为42
    EventData event2 = { 30, "type2" };//消息类型为"type2"的事件,消息内容为30

    eventBus.publish(event1);//这里的消息可以被"Subscriber 1"和"Subscriber 2"同时捕获订阅消息,消息内容 42
    eventBus.publish(event2);//这里的消息可以被"Subscriber 2"捕获订阅消息,而"Subscriber 1"只能订阅"type1"类型的消息,消息内容 30

    return 0;
}

 输出结果:

Subscriber 1 received event with value : 42 and type : type1
Subscriber 2 received event with value : 42 and type : type1
Subscriber 2 received event with value : 30 and type : type2

 

posted @ 2024-10-09 10:03  南水之源  阅读(62)  评论(0编辑  收藏  举报