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

news/2025/1/15 5:25:43/

观察者模式是一种行为型设计模式,允许一个对象(被观察者)状态发生变化时通知一组依赖它的对象(观察者),从而实现对象之间的解耦。在这篇文章中,我们将探讨如何用 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 = namedef 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.ppmy.cn/news/1563230.html

相关文章

EJB与微服务:Java的秘密武器

1.1 EJB&#xff08;Enterprise JavaBeans&#xff09; EJB是一种基于Java的企业级组件模型&#xff0c;主要用于构建大型、分布式和事务性的企业级应用程序。EJB在EJB容器中运行&#xff0c;该容器负责各种系统级服务&#xff0c;包括事务管理、安全性和并发控制。EJB的设计理…

微信小程序集成Vant Weapp移动端开发的框架

什么是Vant Weapp Vant 是一个轻量、可靠的移动端组件库&#xff0c;于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本&#xff0c;并由社区团队维护 React 版本和支付宝小程序版本。 官网地睛&#xff1a;介绍 - Vant Weapp (vant-ui.gith…

51单片机入门基础

目录 一、基础知识储备 &#xff08;一&#xff09;了解51单片机的基本概念 &#xff08;二&#xff09;掌握数字电路基础 &#xff08;三&#xff09;学习C语言编程基础 二、开发环境搭建 &#xff08;一&#xff09;硬件准备 &#xff08;二&#xff09;软件准备 三、…

移动应用安全:保护用户隐私与数据的关键解决方案

移动应用安全为何如此重要&#xff1f; 随着智能设备的普及和移动应用的快速增长&#xff0c;移动应用已成为人们日常生活的重要组成部分。然而&#xff0c;移动应用安全问题也日益严峻。用户隐私泄露、数据被盗、恶意软件攻击等问题给个人和企业都带来了巨大的风险。 移动应用…

对受控组件和非受控组件的理解?应用场景?

受控组件与非受控组件的理解与应用 在 React 中&#xff0c;组件可以通过两种方式管理表单元素的状态&#xff1a;受控组件和非受控组件。这两者在处理表单输入数据时有很大的区别&#xff0c;理解它们的应用场景和优劣对于开发者来说非常重要。 目录结构&#xff1a; 受控组…

如何在 Linux、MacOS 以及 Windows 中打开控制面板

控制面板不仅仅是一系列图标和菜单的集合&#xff1b;它是通往优化个人计算体验的大门。通过它&#xff0c;用户可以轻松调整从外观到性能的各种参数&#xff0c;确保他们的电脑能够完美地适应自己的需求。无论是想要提升系统安全性、管理硬件设备&#xff0c;还是简单地改变桌…

开源的镜像扫描的软件

是的&#xff0c;有许多开源的镜像扫描工具可以生成详细的扫描报告。以下是几款常用的开源镜像扫描工具&#xff0c;它们都支持生成报告&#xff1a; 1. Trivy 简介&#xff1a;Trivy 是一款简单易用的开源漏洞扫描工具&#xff0c;支持容器镜像、文件系统和 Git 仓库的扫描。…

ARP-Batch-Retargeting 部署实战

git 地址&#xff1a; https://github.com/Shimingyi/ARP-Batch-Retargeting bpy安装&#xff1a; pypi上搜索 bpy bpy 4.3.0&#xff0c;4.2.0版本报错&#xff1a; Traceback (most recent call last):File "E:\project\jijia_4d\retarget\ARP-Batch-Retargeting-…