C++如何实现观察者设计模式?C++代码解耦实战【设计模式】
发布时间 - 2025-12-25 00:00:00 点击率:次观察者模式在C++中通过抽象基类解耦Subject与Observer,用std::vector+weak_ptr管理观察者并自动清理,模板化SubjectBase提升复用性,具体类仅需继承并调用notify(),新增观察者零侵入。
观察者模式在C++中核心是解耦“被观察者”(Subject)和“观察者”(Observer),让两者
只依赖抽象,不依赖具体实现。关键在于用抽象类定义接口、用容器管理观察者、用虚函数触发通知——不用信号槽、不依赖第三方库,纯标准C++就能落地。
定义抽象观察者和被观察者接口
先写两个纯虚基类:Observer 声明 update() 接口,Subject 声明 attach()/detach()/notify() 接口。所有具体类都继承它们,这样新增观察者或被观察者时,原有代码完全不用改。
注意:Observer 的 update() 通常接收 const Subject& 或 shared_ptr
实现可复用的 Subject 基类模板
把通用逻辑抽成模板,减少重复代码。例如:
// 模板化 Subject 基类,自动管理 weak_ptr 观察者
template
class SubjectBase {
protected:
std::vector<:weak_ptr>> observers_;
public:
void attach(std::shared_ptr
observers_.push_back(obs);
}
void notify() const {
for (auto it = observers_.begin(); it != observers_.end();) {
if (auto obs = it->lock()) {
obs->update(*this);
++it;
} else {
it = observers_.erase(it); // 自动清理已销毁的观察者
}
}
}
};
具体业务类按需继承并触发通知
比如一个温度传感器类:
class TemperatureSensor : public SubjectBase
private:
double temperature_ = 0.0;
public:
void setTemperature(double t) {
temperature_ = t;
notify(); // 数据一变就广播,不关心谁在监听
}
double getTemperature() const { return temperature_; }
};
再写具体观察者,比如控制台打印器和日志记录器,都只实现自己的 update(),互不影响:
- ConsoleDisplay::update() —— printf 当前温度
- Logger::update() —— 写入文件或发网络请求
使用时只需组合,不修改已有类
main() 里创建对象、建立关系即可:
int main() {
auto sensor = std::make_shared
auto display = std::make_shared
auto logger = std::make_shared
sensor->attach(display);
sensor->attach(logger);
sensor->setTemperature(25.6); // 自动触发 display 和 logger
sensor->setTemperature(26.1); // 同样自动通知
}
以后加新功能(比如发邮件告警),只要写个 EmailAlert 类继承 Observer,实现 update(),再 attach 进去——零侵入、无编译依赖、职责清晰。
基本上就这些。不复杂但容易忽略 weak_ptr 清理、const 正确性、以及模板接口的泛化粒度。写熟了,一个项目里几十个松耦合的通知场景,都能靠这几行基类搞定。
# ai
# c++
# oled
# red
# if
# for
# printf
# const
# auto
# int
# double
# void
# 循环
# 继承
# 虚函数
# 接口
# 类模板
# class
# public
# private
# protected
# 对象
# this
# display
# 传感器
# 自己的
# 复用
# 不依赖
# 记录器
# 就能
# 都能
# 已有
# 只需
# 第三方
# 谁在
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】
javascript中对象的定义、使用以及对象和原型链操作小结
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
非常酷的网站设计制作软件,酷培ai教育官方网站?
Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】
Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】
php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】
laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法
Laravel如何生成PDF或Excel文件_Laravel文档导出工具与使用教程
Thinkphp 中 distinct 的用法解析
JavaScript如何实现音频处理_Web Audio API如何工作?
Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】
悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音
网站建设保证美观性,需要考虑的几点问题!
合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?
Android实现代码画虚线边框背景效果
重庆市网站制作公司,重庆招聘网站哪个好?
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
详解Android图表 MPAndroidChart折线图
如何在景安服务器上快速搭建个人网站?
如何用已有域名快速搭建网站?
JS碰撞运动实现方法详解
LinuxCD持续部署教程_自动发布与回滚机制
高防服务器如何保障网站安全无虞?
WordPress 子目录安装中正确处理脚本路径的完整指南
Laravel路由怎么定义_Laravel核心路由系统完全入门指南
Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用
Laravel如何使用withoutEvents方法临时禁用模型事件
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?
浅谈javascript alert和confirm的美化
如何快速上传建站程序避免常见错误?
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
如何在万网主机上快速搭建网站?
Laravel如何使用Livewire构建动态组件?(入门代码)
焦点电影公司作品,电影焦点结局是什么?
Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理
如何在腾讯云服务器快速搭建个人网站?
如何快速搭建高效服务器建站系统?
如何彻底删除建站之星生成的Banner?
Laravel如何使用Vite进行前端资源打包?(配置示例)
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
C++用Dijkstra(迪杰斯特拉)算法求最短路径
Laravel定时任务怎么设置_Laravel Crontab调度器配置
零服务器AI建站解决方案:快速部署与云端平台低成本实践
Python正则表达式进阶教程_复杂匹配与分组替换解析
Laravel Session怎么存储_Laravel Session驱动配置详解
Laravel如何处理文件下载请求?(Response示例)

