C++ 观察者模式

目录

什么是观察者模式?

观察者模式的特点:

观察者模式的结构

观察者模式的典型 UML 图:

如何使用观察者模式设计事件通知机制

1. 定义观察者接口

2. 定义被观察者(Subject)

3. 实现具体的观察者类

4. 将所有部分整合到一起

5. 分析观察者模式

观察者模式的优缺点

优点:

缺点:

观察者模式的使用场景

改进与扩展

总结


什么是观察者模式?

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象之间的一对多依赖关系。当一个对象(被观察者Subject)的状态发生变化时,所有依赖它的对象(观察者Observer)都会自动收到通知并更新。观察者模式使得对象之间的耦合关系松散化,增强了系统的可扩展性和灵活性。

观察者模式的特点:
  1. 一对多依赖:观察者模式允许一个对象(被观察者)通知多个依赖它的对象(观察者),使它们能够感知到状态的变化。
  2. 松散耦合:被观察者和观察者之间的关系是松耦合的,被观察者只需知道观察者实现了某个接口,而不需要关心观察者的具体实现。
  3. 事件通知机制:观察者模式通常用于实现事件通知机制,当某个事件发生时,被观察者可以通知所有的观察者,观察者根据通知做出反应。

观察者模式的结构

观察者模式的核心结构包括两个角色:

  • 被观察者(Subject):维护一个观察者列表,提供注册和删除观察者的方法,并在状态变化时通知所有观察者。
  • 观察者(Observer):定义一个接口,要求所有的观察者实现一个更新方法,当被观察者的状态变化时,观察者将被通知。
观察者模式的典型 UML 图:
+-----------------+        +-------------------+
|    Subject      |<-------|    Observer        |
+-----------------+        +-------------------+
| + attach()      |        | + update()         |
| + detach()      |        +-------------------+
| + notify()      |
+-----------------+
  • Subject:被观察者,维护观察者列表并在状态改变时通知观察者。
  • Observer:观察者,定义 update() 方法以在接收到通知时更新自身状态。

如何使用观察者模式设计事件通知机制

观察者模式非常适合事件驱动系统中的事件通知机制。下面通过 C++ 实现观察者模式,展示如何设计这种通知机制。

1. 定义观察者接口

观察者接口定义了一个 update() 方法,所有的观察者都必须实现这个方法以响应通知。

#include <iostream>
#include <vector>
#include <memory>

// 观察者接口
class Observer {
public:
    virtual void update(const std::string& message) = 0;
    virtual ~Observer() = default;
};
2. 定义被观察者(Subject)

被观察者负责维护一个观察者列表,提供注册(attach)、注销(detach)观察者的方法,并在状态发生变化时通知所有的观察者(notify)。

class Subject {
private:
    std::vector<std::shared_ptr<Observer>> observers;

public:
    // 注册观察者
    void attach(std::shared_ptr<Observer> observer) {
        observers.push_back(observer);
    }
    
    // 注销观察者
    void detach(std::shared_ptr<Observer> observer) {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }
    
    // 通知所有观察者
    void notify(const std::string& message) {
        for (auto& observer : observers) {
            observer->update(message);  // 调用观察者的更新方法
        }
    }
};
3. 实现具体的观察者类

观察者类需要实现 Observer 接口的 update() 方法,以便能够响应来自被观察者的通知。

class ConcreteObserver : public Observer {
private:
    std::string name;

public:
    ConcreteObserver(const std::string& name) : name(name) {}
    
    // 当收到通知时更新状态
    void update(const std::string& message) override {
        std::cout << name << " received update: " << message << std::endl;
    }
};
4. 将所有部分整合到一起

main() 函数中,我们可以创建被观察者和观察者对象,并通过 Subjectattach() 方法注册观察者。然后,通过调用 notify() 方法来通知观察者。

int main() {
    // 创建被观察者
    Subject subject;

    // 创建观察者
    std::shared_ptr<Observer> observer1 = std::make_shared<ConcreteObserver>("Observer 1");
    std::shared_ptr<Observer> observer2 = std::make_shared<ConcreteObserver>("Observer 2");

    // 注册观察者
    subject.attach(observer1);
    subject.attach(observer2);

    // 被观察者发生变化,通知观察者
    subject.notify("Event 1 occurred!");

    // 注销一个观察者
    subject.detach(observer1);

    // 再次通知观察者
    subject.notify("Event 2 occurred!");

    return 0;
}

输出:

Observer 1 received update: Event 1 occurred!
Observer 2 received update: Event 1 occurred!
Observer 2 received update: Event 2 occurred!
5. 分析观察者模式

在上面的实现中:

  • Subject 维护了一个观察者列表,通过 attachdetach 方法管理观察者。
  • Observer 定义了 update() 方法,当 Subject 发生变化时,会通知所有注册的观察者,调用它们的 update() 方法。
  • 观察者对象可以随时注册或注销,它们之间是松耦合的。Subject 只需知道 Observer 实现了 update() 方法,而不关心具体的观察者类。

观察者模式的优缺点

优点:
  1. 解耦:观察者和被观察者是松耦合的,被观察者不需要知道具体的观察者实现,增加了代码的灵活性和可维护性。
  2. 支持广播通信:一个被观察者可以同时通知多个观察者,自动更新它们的状态。
  3. 动态增加观察者:观察者可以在运行时动态添加或删除,而不影响被观察者的实现。
缺点:
  1. 通知开销:如果观察者数量很多,通知所有观察者可能导致性能问题。
  2. 顺序依赖:如果观察者之间存在依赖关系,通知的顺序可能导致问题。
  3. 观察者可能对状态变化反应不及时:由于观察者的状态更新依赖于通知机制,通知的时机和顺序可能会导致观察者的状态更新不及时。

观察者模式的使用场景

观察者模式非常适合以下场景:

  1. 事件驱动系统:当系统中某个对象的状态变化需要通知其他对象时,可以使用观察者模式。例如,GUI 事件处理(按钮点击、窗口大小变化等)、实时数据监控系统等。
  2. 订阅-发布机制:在一些消息传递系统中,发布者和订阅者可以通过观察者模式解耦。
  3. 模型-视图-控制器(MVC)架构:在 MVC 模式中,模型层的状态变化需要通知视图层进行更新,这通常使用观察者模式实现。
  4. 日志系统:在日志系统中,可以将日志的不同输出渠道(如文件、控制台、网络)作为观察者,当日志事件发生时,通知所有输出渠道处理日志。

改进与扩展

在实际应用中,观察者模式可以结合其他设计模式进行改进和扩展:

  1. 推模型和拉模型
    • 推模型:被观察者主动将变更的细节推送给观察者,观察者只能被动接受信息。
    • 拉模型:被观察者通知观察者,但不提供具体的变化信息,观察者主动向被观察者拉取变化的详细内容。

目前实现的方式是推模型,你可以根据需求实现拉模型。

  1. 结合事件总线:对于复杂的系统,可以将事件总线与观察者模式结合,集中处理事件通知和订阅,避免多个对象直接相互依赖。

总结

  • 观察者模式 是一种行为型设计模式,用于定义对象之间的一对多依赖关系。它通过将对象的状态变化通知多个依赖的观察者,实现对象之间的松耦合。
  • 观察者模式特别适合事件驱动系统、消息传递系统、MVC 架构等场景,有助于提高系统的灵活性和可维护性。
  • 通过使用 Subject 来管理观察者列表,观察者可以在运行时动态地添加和移除,观察者模式可以很好地解耦系统中的不同模块。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值