当前位置: 首页 > article >正文

深入理解观察者模式 —— Qt信号槽机制的实现

观察者模式是一种行为型设计模式,允许一个对象(被观察者)状态发生变化时通知一组依赖它的对象(观察者),从而实现对象之间的解耦。在这篇文章中,我们将探讨如何用 C++Python 实现观察者模式,并在代码中清晰地体现这一设计模式的核心思想。

其实Qt的信号槽机制,就是借住了这一设计模式,并对其进行了一些扩展。由于Qt广泛的被C++和Python用户使用,所以这里给出Python和C++两个版本的简单实现示例。


观察者模式的核心

  1. Subject(被观察者)
    维护观察者列表并提供注册、移除和通知观察者的机制。

  2. Observer(观察者)
    定义接口,提供 update 方法,供被观察者在状态变化时调用。

  3. ConcreteObserver(具体观察者)
    实现观察者接口,响应被观察者的通知。


C++ 实现观察者模式

代码实现
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>

// 抽象观察者接口
class Observer {
public:
    virtual ~Observer() = default;
    virtual void update(const std::string& message) = 0;
};

// 被观察者类
class Subject {
public:
    void attach(const std::shared_ptr<Observer>& observer) {
        m_observers.push_back(observer);
    }

    void detach(const std::shared_ptr<Observer>& observer) {
        m_observers.erase(
            std::remove(m_observers.begin(), m_observers.end(), observer),
            m_observers.end()
        );
    }

    void notify(const std::string& message) {
        for (const auto& observer : m_observers) {
            if (observer) {
                observer->update(message);
            }
        }
    }

private:
    std::vector<std::shared_ptr<Observer>> m_observers; // 观察者列表
};

// 具体观察者
class ConcreteObserver : public Observer {
public:
    explicit ConcreteObserver(const std::string& name) : m_name(name) {}

    void update(const std::string& message) override {
        std::cout << "Observer [" << m_name << "] received message: " << message << std::endl;
    }

private:
    std::string m_name; // 观察者名称
};

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

    // 创建具体观察者
    auto observer1 = std::make_shared<ConcreteObserver>("Observer1");
    auto observer2 = std::make_shared<ConcreteObserver>("Observer2");

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

    // 通知所有观察者
    std::cout << "Sending notification: 'Event A occurred'" << std::endl;
    subject.notify("Event A occurred");

    // 移除一个观察者
    subject.detach(observer1);

    // 再次通知
    std::cout << "Sending notification: 'Event B occurred'" << std::endl;
    subject.notify("Event B occurred");

    return 0;
}
输出结果
Sending notification: 'Event A occurred'
Observer [Observer1] received message: Event A occurred
Observer [Observer2] received message: Event A occurred
Sending notification: 'Event B occurred'
Observer [Observer2] received message: Event B occurred

Python 实现观察者模式

代码实现
from typing import List

# 抽象观察者接口
class Observer:
    def update(self, message: str):
        """被通知时调用的方法"""
        raise NotImplementedError("Subclass must implement abstract method")

# 被观察者类
class Subject:
    def __init__(self):
        self._observers: List[Observer] = []  # 观察者列表

    def attach(self, observer: Observer):
        """注册观察者"""
        if observer not in self._observers:
            self._observers.append(observer)

    def detach(self, observer: Observer):
        """移除观察者"""
        if observer in self._observers:
            self._observers.remove(observer)

    def notify(self, message: str):
        """通知所有观察者"""
        for observer in self._observers:
            observer.update(message)

# 具体观察者
class ConcreteObserver(Observer):
    def __init__(self, name: str):
        self._name = name

    def update(self, message: str):
        print(f"Observer {self._name} received message: {message}")

# 测试代码
if __name__ == "__main__":
    # 创建被观察者
    subject = Subject()

    # 创建具体观察者
    observer1 = ConcreteObserver("Observer1")
    observer2 = ConcreteObserver("Observer2")

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

    # 通知所有观察者
    print("Sending notification: 'Event A occurred'")
    subject.notify("Event A occurred")

    # 移除一个观察者
    subject.detach(observer1)

    # 再次通知
    print("Sending notification: 'Event B occurred'")
    subject.notify("Event B occurred")
输出结果
Sending notification: 'Event A occurred'
Observer Observer1 received message: Event A occurred
Observer Observer2 received message: Event A occurred
Sending notification: 'Event B occurred'
Observer Observer2 received message: Event B occurred

比较与分析

  1. C++ 和 Python 的对比

    • C++ 通过智能指针(std::shared_ptr)管理观察者生命周期,防止内存泄漏。
    • Python 利用动态特性和内置容器(如 list),代码更简洁,开发效率更高。
  2. 扩展性

    • 两种语言都可以轻松扩展为支持更复杂的通知机制,例如传递多参数、支持异步事件等。

总结

观察者模式通过将事件通知和响应解耦,为多对象之间的通信提供了一种灵活的解决方案。无论是 C++ 还是 Python,都可以方便地实现这一模式,并根据需求进行扩展。

思考

值得关注的一点,需要读者自己去尝试和实现:

  • 如何在信号槽机制中添加自定义参数

http://www.kler.cn/a/503923.html

相关文章:

  • PyQt5
  • 基于ESP8266 wifimanager实现WiFi配置及天气显示
  • FPGA的 基本结构(Xilinx 公司Virtex-II 系列FPGA )
  • 本地用docker装mysql
  • 主数据系统建设模式分析
  • MATLAB学习笔记目录
  • 通过一个算法的设计来了解栈的一些应用
  • 【Audition】Audition如何在波形中插入静音且插入边缘不做平滑处理
  • 使用sqlplus的easy connect时如何指定是链接到shared server还是dedicated process
  • 【01】AE特效开发制作特技-Adobe After Effects-AE特效制作快速入门-制作飞机,子弹,爆炸特效以及导出png序列图-优雅草央千澈
  • 三相无刷电机控制|FOC理论04 - 克拉克变换 + 帕克变换的最终目标
  • ubuntu Android : adb logcat 过滤多个log
  • RAG 测评基线
  • git相关操作
  • Linux入门——权限
  • 学习笔记080——如何备份服务器中Docker创建的MySQL数据库数据?
  • [Linux] GDB 和 CGDB的使用及理解
  • 国产编辑器EverEdit - 打印与打印预览
  • 如何编写和运行 Lua 脚本优化复杂的 Redis 操作
  • 计算机视觉算法实战——视频分析(Video Analysis)
  • Linux 服务器挖矿木马防护实战:快速切断、清理与加固20250114
  • 【自然语言处理】P1 自然语言处理概述
  • 【SpringSecurity】SpringSecurity安全框架登录校验流程与登录配置示例
  • 时序数据库的订阅对比:TDengine vs InfluxDB 谁更强?
  • CentOS 6.8 安装 Nginx
  • 在ES6模块中导入和导出