发布者订阅者模式模型

版本一
#include <iostream>
#include <vector>
#include <unordered_map>
#include <functional>
#include <mutex>

class Subscriber {
public:
    virtual void update(const std::string& topic, const std::string& message) = 0;
};

class Publisher {
public:
    // 订阅某个主题
    void subscribe(const std::string& topic, Subscriber* subscriber) {
        std::lock_guard<std::mutex> lock(mutex_); // 使用互斥锁保护订阅者列表的访问
        subscribers[topic].push_back(subscriber); // 将订阅者添加到对应主题的订阅者列表中
    }

    // 取消订阅某个主题
    void unsubscribe(const std::string& topic, Subscriber* subscriber) {
        std::lock_guard<std::mutex> lock(mutex_); // 使用互斥锁保护订阅者列表的访问
        if (subscribers.find(topic) != subscribers.end()) {
            auto& topicSubscribers = subscribers[topic];
            topicSubscribers.erase(std::remove(topicSubscribers.begin(), topicSubscribers.end(), subscriber), \
                                   topicSubscribers.end()); // 从对应主题的订阅者列表中移除订阅者
        }
    }

    // 发布消息到某个主题
    void publish(const std::string& topic, const std::string& message) {
        std::lock_guard<std::mutex> lock(mutex_); // 使用互斥锁保护订阅者列表的访问
        if (subscribers.count(topic) > 0) { // 检查是否有订阅该主题的订阅者
            auto& topicSubscribers = subscribers[topic];
            for (auto subscriber : topicSubscribers) {
                subscriber->update(topic, message); // 更新订阅者的消息
            }
        }
    }

private:
    std::unordered_map<std::string, std::vector<Subscriber*>> subscribers; // 存储订阅者的unordered_map
    std::mutex mutex_; // 互斥锁,用于保护订阅者列表的访问
};

class ConcreteSubscriber : public Subscriber {
    std::string name_; // 订阅者名字

public:
    ConcreteSubscriber(const std::string& name) : name_(name) {}

    // 接收到消息时的处理逻辑
    void update(const std::string& topic, const std::string& message) override {
        std::cout << name_ << " received message on topic " << topic << ": " << message << std::endl;
    }
};

int main() {
    Publisher publisher;

    ConcreteSubscriber subscriber1("Subscriber 1");
    ConcreteSubscriber subscriber2("Subscriber 2");
    ConcreteSubscriber subscriber3("Subscriber 3");

    // 订阅不同主题的订阅者
    publisher.subscribe("Topic 1", &subscriber1);
    publisher.subscribe("Topic 1", &subscriber2);
    publisher.subscribe("Topic 2", &subscriber2);
    publisher.subscribe("Topic 2", &subscriber3);

    // 发布消息到不同主题
    publisher.publish("Topic 1", "Hello from Topic 1");
    publisher.publish("Topic 2", "Hello from Topic 2");

    // 取消某个订阅者的订阅
    publisher.unsubscribe("Topic 1", &subscriber2);

    // 再次发布消息到不同主题
    publisher.publish("Topic 1", "Hello again from Topic 1");
    publisher.publish("Topic 2", "Hello again from Topic 2");

    return 0;
}
版本二
#include <iostream>
#include <vector>
#include <unordered_map>
#include <functional>
#include <mutex>
#include <algorithm>

class Subscriber;

class Publisher
{
    std::unordered_map<std::string, std::vector<Subscriber *>> _subscribers; // 记录订阅者的数据结构
    std::mutex _mutex;                                                       // 互斥锁,用于保护订阅者列表的并发访问

public:
    // 订阅指定主题的通知
    void subscribe(const std::string &topic, Subscriber *subscriber)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        _subscribers[topic].push_back(subscriber);
    }

    // 取消订阅指定主题的通知
    void unsubscribe(const std::string &topic, Subscriber *subscriber)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        if (_subscribers.find(topic) != _subscribers.end())
        {
            auto &topicSubscribers = _subscribers[topic];
            topicSubscribers.erase(std::remove(topicSubscribers.begin(), topicSubscribers.end(), subscriber),
                                   topicSubscribers.end());
        }
    }

    // 取消订阅指定订阅者所有主题
    void unsubscribeAllTopics(Subscriber *subscriber)
    {
        std::lock_guard<std::mutex> lock(_mutex);
        for (auto &it : _subscribers)
        {
            auto &topicSubscribers = it.second;
            topicSubscribers.erase(std::remove(topicSubscribers.begin(), topicSubscribers.end(), subscriber),
                                   topicSubscribers.end());
        }
    }

    // 发布指定主题的消息
    void publish(const std::string &topic, const std::string &message);
};

class Subscriber
{
public:
    virtual void update(const std::string &topic, const std::string &message) = 0;

    // 订阅多个主题
    void subscribeToTopics(Publisher &publisher, const std::vector<std::string> &topics)
    {
        for (const auto &topic : topics)
        {
            publisher.subscribe(topic, this);
        }
    }

    // 取消订阅多个主题
    void unsubscribeFromTopics(Publisher &publisher, const std::vector<std::string> &topics)
    {
        for (const auto &topic : topics)
        {
            publisher.unsubscribe(topic, this);
        }
    }

    // 取消订阅所有主题
    void unsubscribefromAllTopics(Publisher &publisher)
    {
        publisher.unsubscribeAllTopics(this);
    }
};

void Publisher::publish(const std::string &topic, const std::string &message)
{
    std::lock_guard<std::mutex> lock(_mutex);
    if (_subscribers.count(topic) > 0)
    {
        for (const auto &subscriber : _subscribers[topic])
        {
            subscriber->update(topic, message);
        }
    }
}

class ConcreteSubscriber : public Subscriber
{
    std::string _name;

public:
    ConcreteSubscriber(const std::string &name) : _name(name) {}

    // 更新接收到的消息
    void update(const std::string &topic, const std::string &message) override
    {
        std::cout << _name << " received message on topic " << topic << ": " << message << std::endl;
    }
};

int main()
{
    Publisher publisher;

    std::vector<std::string> topics1 = {"Topic 1", "Topic 2"};
    std::vector<std::string> topics2 = {"Topic 1", "Topic 3"};

    ConcreteSubscriber subscriber1("Subscriber 1");
    ConcreteSubscriber subscriber2("Subscriber 2");

    // 订阅多个主题
    subscriber1.subscribeToTopics(publisher, topics1);
    subscriber2.subscribeToTopics(publisher, topics2);

    // 发布消息
    publisher.publish("Topic 1", "Hello from Topic 1");
    publisher.publish("Topic 2", "Hello from Topic 2");
    publisher.publish("Topic 3", "Hello from Topic 3");

    // 取消订阅多个主题
    subscriber1.unsubscribeFromTopics(publisher, topics1);
    subscriber2.unsubscribefromAllTopics(publisher);

    // 再次发布消息,订阅者1不会接收到与主题1相关的消息
    publisher.publish("Topic 1", "Hello from Topic 1");
    publisher.publish("Topic 2", "Hello from Topic 2");
    publisher.publish("Topic 3", "Hello from Topic 3");

    return 0;
}```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值