C++如何实现一个观察者模式(Observer Pattern)?(代码示例)


观察者模式通过抽象基类解耦发布者与订阅者,Subject用容器管理Observer并通知状态变化,Observer需实现update方法,需注意weak_ptr防循环引用。

观察者模式在 C++ 中可以通过抽象基类定义接口,用容器管理观察者,再由被观察者(Subject)在状态变化时通知所有注册的观察者。核心是解耦发布者与订阅者,避免硬依赖。

定义 Observer 接口

所有观察者需实现统一的更新方法,通常接收被观察者指针或事件数据:

class Observer {
public:
    virtual ~Observer() = default;
    virtual void update(const std::string& message) = 0; // 简单消息通知
};

实现 Subject 基类(被观察者)

维护观察者列表,提供注册、移除和通知能力。注意使用 weak_ptr 或手动管理生命周期,避免循环引用:

#include 
#include 
#include 

class Subject {
protected:
    std::vector> observers;

public:
    void attach(std::shared_ptr obs) {
        if (obs && std::find(observers.begin(), observers.end(), obs) == observers.end()) {
            observers.push_back(obs);
        }
    }

    void detach(std::shared_ptr obs) {
        observers.erase(
            std::remove(observers.begin(), observers.end(), obs),
            observers.end()
        );
    }

    void notify(const std::string& msg) {
        for (auto& obs : observers) {
            if (obs) obs->update(msg); // 安全调用
        }
    }
};

具体实现:天气站示例

一个 WeatherStation 继承 Subject,当温度变化时通知所有观察者:

class WeatherStation : public Subject {
private:
    double temperature = 0.0;

public:
    void setTemperature(double temp) {
        temperature = temp;
        notify("Temperature changed to " + std::to_string(temp) + "°C");
    }
};

class PhoneDisplay : public Observer {
public:
    void update(const std::string& message) override {
        std::cout << "[Phone] " << message << std::endl;
    }
};

class WebDisplay : public Observer {
public:
    void update(const std::string& message) override {
        std::cout << "[Web] " << message << std::endl;
    }
};

使用方式

创建被观察者和多个观察者,注册后触发通知:

int main() {
    auto station = std::make_shared();
    auto phone = std::make_shared();
    auto web = std::make_shared();

    station->attach(phone);
    station->attach(web);

    station->setTemperature(25.5); // 输出两条通知
    station->detach(phone);
    station->setTemperature(27.0); // 只输出 Web 通知

    return 0;
}

基本上就这些。关键点在于用 shared_ptr 管理观察者生命周期,notify 前检查空指针,以及让具体类只关心自己的 update 行为。不需要模板也能清晰表达意图,进阶可结合 std::function 或事件总线扩展。


# go  # c++  # 循环  # 指针  # 继承  # 接口  # 空指针  # function  # 事件  # 自己的  # 进阶  # 多个  # 不需要  # 也能  # 可以通过  # 两条  # 再由  # 移除  # 需注意 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Win11文件夹预览图不显示怎么办_Win11缩略图缓存重建修复【教程】  Windows10如何重置此电脑_Windows10电脑重置方法【步骤】  如何使用Golang反射创建map对象_动态生成键值映射  Win11怎么退出高对比度模式_Win11取消反色显示快捷键【修复】  Win11怎么关闭任务栏小组件_Windows11隐藏任务栏天气图标  Linux如何安装Golang环境_Linux下Go语言开发包配置【方法】  Win11怎么关闭搜索历史_Win11清除设备上的搜索历史记录  Win11关机快捷键是什么_Win11快速关机方法【大全】  php485返回数据不完整怎么办_php485数据分包重组处理方法【教程】  如何在Golang中理解指针比较_Golang地址比较与相等判断  c++20的std::format怎么用 比printf更安全高效的格式化方法【详解】  Python异步网络编程_aiohttp说明【指导】  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  Win11怎么开启远程桌面连接_Windows11系统属性远程设置  Win11怎么关闭用户账户控制UAC_Windows11更改通知设置等级  如何在Golang中处理数据库事务错误_回滚和日志记录  Win11怎么设置任务栏透明_Windows11使用工具美化任务栏  Win11系统更新后黑屏怎么办 Win11更新黑屏修复教程【方法】  Win11如何设置系统声音_Win11系统声音调整教程【攻略】  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  Win10 BitLocker加密教程 Win10给磁盘驱动器上锁【安全】  Win10电脑怎么设置IP地址_Windows10网络属性固定IP配置  Python邮件系统自动化教程_批量发送解析与模板应用  Win11文件扩展名怎么显示 Win11查看文件后缀名设置【步骤】  php485支持哪些操作系统_php485跨系统支持情况介绍【解答】  PythonWeb前后端整合项目教程_FastAPIReact完整实例  Mac如何创建和管理多个桌面空间_Mac高效多任务处理【技巧】  Win11怎么设置默认PDF阅读器 Win11修改PDF打开方式【步骤】  Windows 11如何开启文件夹加密(EFS)_Windows 11文件属性中加密内容以保护数据  php转mp4怎么保留字幕_php处理带字幕视频转换说明【说明】  php增删改查需要哪些扩展_开启mysqli或pdo扩展方法【说明】  短链接还原php提示内存不足_调整PHP内存限制设置【技巧】  Python安全爬虫设计_IP代理池与验证码识别策略解析  如何使用Golang log设置日志输出格式_Golang log日志格式示例  Windows怎样关闭开始菜单推荐广告_Windows关闭开始菜单推荐设置【步骤】  Python集合操作技巧_高效去重解析【教程】  Windows服务启动类型恢复方法_错误修改导致的系统服务异常  如何使用Golang构建简易投票统计功能_Golang投票数据汇总与展示示例  Python类装饰器使用_元编程解析【教程】  c++ try_emplace用法_c++ map高效插入数据  Windows怎样关闭桌面弹窗广告_Windows关闭桌面弹窗设置【教程】  Win11怎么设置单手模式_Win11触控键盘布局调整教程【技巧】  Mac如何与安卓手机传文件_Mac和Android设备互通【必备工具】  php8.4如何调用com组件_php8.4windows下com操作指南【教程】  Win11 C盘满了怎么清理 Win11磁盘清理和存储感知使用教程【新手必看】  Win11如何设置鼠标灵敏度_Win11鼠标灵敏度调整教程【攻略】  Win10怎么限制单程序CPU占用上限_Win10任务管理器亲和性或第三方工具均衡负载【技巧】  Win11怎么关闭搜索历史 Win11清除搜索框最近记录【隐私】  MAC怎么设置程序窗口永远最前_MAC窗口置顶插件安装与快捷设置【方法】  Win11怎么清理C盘虚拟内存_Win11清理虚拟内存设置【教程】 

 2025-12-20

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.