设计模式---观察者模式(发布-订阅模式)

设计模式---观察者模式(发布-订阅模式)

一、简介

发布-订阅模式是一种消息传递模式,用于实现对象间的一对多依赖关系。在这种模式中:

  • 发布者(Publisher)不直接向订阅者(Subscriber)发送消息
  • 发布者和订阅者通过一个中介(通常称为事件总线或消息代理)进行通信
  • 订阅者可以订阅感兴趣的事件,发布者可以发布事件

这种模式实现了发布者和订阅者的解耦,提高了系统的灵活性和可扩展性。

二、原理

2.1核心组件

Publisher(发布者):产生事件/消息的对象

Subscriber(订阅者):接收并处理事件的对象

Event Bus/Message Broker(事件总线):管理订阅关系,负责将消息从发布者路由到订阅者

2.2工作流程

订阅者向事件总线注册对特定事件的兴趣

发布者向事件总线发布事件

事件总线将事件传递给所有注册的订阅者

三、C++实现

以下是发布-订阅模式的简单C++实现:

C++ 复制代码
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include <memory>

// 前置声明
class EventBus;

// 订阅者接口
class Subscriber {
public:
    virtual ~Subscriber() = default;
    virtual void handleEvent(const std::string& event, const std::string& message) = 0;
};

// 具体订阅者
class ConcreteSubscriber : public Subscriber {
public:
    ConcreteSubscriber(const std::string& name) : name_(name) {}

    void handleEvent(const std::string& event, const std::string& message) override {
        std::cout << name_ << " received event '" << event 
                  << "' with message: " << message << std::endl;
    }

private:
    std::string name_;
};

// 事件总线
class EventBus {
public:
    // 订阅事件
    void subscribe(const std::string& event, Subscriber* subscriber) {
        subscribers_[event].push_back(subscriber);
    }

    // 取消订阅
    void unsubscribe(const std::string& event, Subscriber* subscriber) {
        auto& subs = subscribers_[event];
        subs.erase(std::remove(subs.begin(), subs.end(), subscriber), subs.end());
    }

    // 发布事件
    void publish(const std::string& event, const std::string& message) {
        if (subscribers_.find(event) != subscribers_.end()) {
            for (auto subscriber : subscribers_[event]) {
                subscriber->handleEvent(event, message);
            }
        }
    }

private:
    std::map<std::string, std::vector<Subscriber*>> subscribers_;
};

// 发布者
class Publisher {
public:
    Publisher(EventBus& eventBus) : eventBus_(eventBus) {}

    void publish(const std::string& event, const std::string& message) {
        eventBus_.publish(event, message);
    }

private:
    EventBus& eventBus_;
};

int main() {
    EventBus eventBus;

    // 创建订阅者
    ConcreteSubscriber sub1("Subscriber1");
    ConcreteSubscriber sub2("Subscriber2");
    ConcreteSubscriber sub3("Subscriber3");

    // 订阅事件
    eventBus.subscribe("event1", &sub1);
    eventBus.subscribe("event1", &sub2);
    eventBus.subscribe("event2", &sub2);
    eventBus.subscribe("event2", &sub3);

    // 创建发布者
    Publisher publisher(eventBus);

    // 发布事件
    publisher.publish("event1", "First event message");
    publisher.publish("event2", "Second event message");

    // 取消订阅
    eventBus.unsubscribe("event1", &sub2);

    // 再次发布
    publisher.publish("event1", "Event after unsubscribe");

    return 0;
}

代码运行结果:

四、应用场景

  1. GUI系统中的事件处理
  2. 分布式系统中的消息传递
  3. 微服务架构中的服务间通信
  4. 游戏开发中的事件系统
  5. 日志系统和监控系统

优点

  1. 松耦合:发布者和订阅者不需要知道对方的存在
  2. 可扩展性:可以轻松添加新的发布者或订阅者
  3. 灵活性:订阅者可以动态订阅或取消订阅事件

缺点

  1. 调试困难:由于间接性,事件流可能难以跟踪
  2. 性能开销:消息传递可能比直接调用慢
  3. 可能导致内存泄漏:如果订阅者没有正确取消订阅

发布-订阅模式是现代软件架构中非常重要的模式,特别是在需要组件间松散耦合的系统中。

参考文章:

1."牵一发而动全身"------我用观察者模式简单模拟吃鸡

2.《推荐C++ 23种设计模式》系列第十九期:观察者模式【架构设计与实现】

相关推荐
疯狂的代M夫10 分钟前
网络通信流程
网络
小江的记录本17 分钟前
【网络安全】《网络安全常见攻击与防御》(附:《六大攻击核心特性横向对比表》)
java·网络·人工智能·后端·python·安全·web安全
回忆2012初秋1 小时前
工厂方法模式完整实现:GPS转换
设计模式·工厂方法模式
2401_873479402 小时前
应急响应:勒索软件攻击源IP分析,如何通过IP地址查询定位辅助溯源?
网络·tcp/ip·安全·网络安全·ip
拾薪3 小时前
[SuperPower] Brainingstorm - 流程控制架构分析
网络·人工智能·ai·架构·superpower·brainstorming
IMPYLH3 小时前
Linux 的 rm 命令
linux·运维·服务器·网络·bash
white-persist4 小时前
【vulhub shiro 漏洞复现】vulhub shiro CVE-2016-4437 Shiro反序列化漏洞复现详细分析解释
运维·服务器·网络·python·算法·安全·web安全
黄俊懿4 小时前
【架构师从入门到进阶】第五章:DNS&CDN&网关优化思路——第一节:DNS优化
网络·计算机网络·架构·系统架构·cdn·dns·架构设计
胡志辉的博客4 小时前
多智能体协作,不是多开几个 Agent:从中介者模式看 OpenClaw 和 Hermes Agent
人工智能·设计模式·ai·agent·中介者模式·openclaw·herman
shark22222225 小时前
能懂!基于Springboot的用户增删查改(三层设计模式)
spring boot·后端·设计模式