观察者模式中主题直接通知观察者,发布订阅模式通过事件中心解耦通信。前者适用于对象间紧密关联,如Model与View同步;后者适合跨模块通信,如Vue事件总线。两者均需注意取消订阅以避免内存泄漏。

观察者模式和发布订阅模式在J*aScript中常用于解耦组件之间的通信。虽然两者看起来相似,但它们的实现机制和使用场景略有不同。下面分别介绍这两种模式的核心思想与代码实现。
观察者模式(Observer Pattern)
观察者模式定义了一种一对多的依赖关系:当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
在这个模式中,被观察的对象(称为“主题”或Subject)维护一个观察者列表,并在状态变化时主动通知它们。
实现步骤:
- Subject 提供添加、删除和通知观察者的方法
- Observer 实现一个更新方法,用于接收通知
- Subject 状态变化时,遍历观察者列表并调用其 update 方法
代码示例:
```j*ascript class Subject { constructor() { this.observers = []; }addObserver(observer) { this.observers.push(observer); }
removeObserver(observer) { this.observers = this.observers.filter(obs => obs !== observer); }
notify(data) { this.observers.forEach(observer => observer.update(data)); } }
class Observer { constructor(name) { this.name = name; }
update(data) {
console.log(${this.name} 收到通知:, data);
}
}
// 使用示例 const subject = new Subject(); const obs1 = new Observer('观察者A'); const obs2 = new Observer('观察者B');
subject.addObserver(obs1); subject.addObserver(obs2);
subject.notify('状态已更新!'); // 输出: // 观察者A 收到通知:状态已更新! // 观察者B 收到通知:状态已更新!
<H3>发布订阅模式(Publish-Subscribe Pattern)</H3>
<p>发布订阅模式引入了事件通道(或事件中心),发布者和订阅者之间没有直接引用。消息通过事件中心进行中转,实现更彻底的解耦。</p>
<div class="aritcle_card">
<a class="aritcle_card_img" href="/ai/2294">
<img src="https://img.php.cn/upload/ai_manual/001/246/273/175712858367437.png" alt="ChatCut">
</a>
<div class="aritcle_card_info">
<a href="/ai/2294">ChatCut</a>
<p>AI视频剪辑工具</p>
<div class="">
<img src="/static/images/card_xiazai.png" alt="ChatCut">
<span>1086</span>
</div>
&
lt;/div>
<a href="/ai/2294" class="aritcle_card_btn">
<span>查看详情</span>
<img src="/static/images/cardxiayige-3.png" alt="ChatCut">
</a>
</div>
<p>与观察者模式不同,发布者不直接通知订阅者,而是将消息推送给事件中心,由事件中心分发给所有订阅该事件的消费者。</p>
<font color="#000000">
<strong>核心角色:</strong>
<ul>
<li>Publisher:发布事件</li>
<li>Subscriber:订阅感兴趣的事件</li>
<li>Event Channel:负责事件的注册、触发和管理</li>
</ul>
</font>
<p><strong>代码示例:</strong></p>
```j*ascript
class EventCenter {
constructor() {
this.events = {};
}
// 订阅事件
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
// 发布事件
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(callback => callback(data));
}
}
// 取消订阅
off(event, callback) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
}
// 只监听一次
once(event, callback) {
const wrapper = (data) => {
callback(data);
this.off(event, wrapper);
};
this.on(event, wrapper);
}
}
// 使用示例
const eventBus = new EventCenter();
eventBus.on('news', (msg) => {
console.log('新闻订阅者:', msg);
});
eventBus.on('news', (msg) => {
console.log('另一位读者:', msg);
});
eventBus.on('weather', (info) => {
console.log('天气预报:', info);
});
eventBus.emit('news', '今天发生了重大事件!');
// 输出:
// 新闻订阅者: 今天发生了重大事件!
// 另一位读者: 今天发生了重大事件!
eventBus.emit('weather', '明天晴,气温25℃');
// 输出:天气预报: 明天晴,气温25℃观察者模式 vs 发布订阅模式
两者都实现了对象间的松耦合通信,但关键区别在于耦合度和控制权:
- 观察者模式中,Subject 直接管理 Observer 列表,两者存在直接依赖
- 发布订阅模式通过事件中心中介,发布者和订阅者完全不知道对方的存在
- 发布订阅更适合复杂系统中的跨模块通信,如Vue的事件总线、Node.js的 EventEmitter
- 观察者模式更适用于对象间紧密关联的场景,如MVC中的Model与View
基本上就这些。理解它们的区别有助于在实际项目中选择合适的通信机制。不复杂但容易忽略细节,比如取消订阅和内存泄漏问题。
以上就是J*aScript设计模式_观察者与发布订阅实现的详细内容,更多请关注其它相关文章!
# 遍历
# seo全网营销平台运营
# 泰安个人网站建设哪家好
# 大米推广营销案例范文怎么写
# 英山网站建设排名前十
# 燃灯教育SEO教程VIP下载
# 营销推广获客公司
# 太原建设电商网站
# 涧西定制网站推广
# 网站都有哪些推广方式
# 宜宾自考网站建设
# 相关文章
# 感兴趣
# 并在
# vue
# 在这个
# 明天
# 复用
# 另一位
# 发生了
# 适用于
# 区别
# app
# node
# node.js
# js
# java
# javascript
相关栏目:
【
企业资讯168 】
【
行业动态20933 】
【
网络营销52431 】
【
网络学院91036 】
【
运营推广7012 】
【
科技资讯60970 】
相关推荐:
React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性
Golang如何实现状态模式管理对象状态_Golang State模式实现技巧
J*aScript:在map操作中高效处理空数组
批改网学生版PC登录 批改网官网登录系统入口
谷歌推RCS信息存档功能:公司可监控员工私密信息!
顺丰快件物流信息 官方网站查询入口
Windows10怎么开启存储感知 Windows10系统设置自动清理临时文件释放C盘空间【教程】
Go语言中JSON数据解析与字段访问教程
Golang如何实现容器化日志收集与分析_Golang容器日志收集分析方法
AO3官方可用镜像 Archive of Our Own网页版最新入口
优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践
学习通在线学习平台 学习通网页版直接进入课程中心
J*aScript map 方法中处理循环元素为空数组的策略
vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧
使用 Pandas 高效处理 .dat 文件:字符清理与数据计算
一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法
Composer如何在生产环境安全地执行composer update
抖音网页版怎么|直播|_抖音网页版开播操作指南
PDF文件体积过大处理_PDF压缩技巧详解
QQ邮箱正确登录入口_QQ邮箱官方网站使用地址
深入理解Google Cloud Datastore查询:祖先路径与数据一致性
Lar*el如何正确地在控制器和模型之间分配逻辑_Lar*el代码职责分离与架构建议
如何解决电商平台定制报价请求的“黑洞”问题,SprykerQuoteRequest模块助你提升客户体验与销售效率
J*aScript井字棋(Tic-Tac-Toe)核心交互逻辑实现教程
CSS Flexbox如何实现多行排列_flex-wrap wrap自动换行显示
J*aScript中高效管理与清空动态列表:避免循环陷阱
今日头条怎么同步内容到抖音_今日头条内容同步到抖音教程
怎么在浏览器上运行HTML文件_浏览器运行HTML文件技巧【技巧】
c++如何实现一个简单的软件渲染器_c++从零开始的3D图形学
如何使用 Excel 发布器与 Power BI 分享 Excel 洞察
将HTML Canvas内容转换为可上传的图像文件(File对象)
Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】
AWS EC2实例间SQL Server连接超时:安全组配置与故障排除指南
126邮箱账号注册 电脑版登录入口
抖音网页版快捷访问 抖音网页版网页版入口操作教程
Highcharts 雷达图径向轴标签定制指南:利用多Y轴实现数值标注
C++ string find函数返回值npos详解_C++字符串查找失败的判断条件
AO3中文官网链接_AO3网页版稳定镜像站
c++如何使用Meson构建系统_c++比CMake更快的构建工具
Win11如何设置屏幕保护程序 Win11屏保设置与取消方法【教程】
消息称三星明年 2 月正式发布 HBM4,与 SK 海力士同台竞技
虚幻5科幻题材ARPG大作遭取消!本是《奇异人生》厂商新作
基于动态规划的房屋花卉种植最小成本算法详解
PyTorch模型训练效果不佳?深入剖析常见错误与调试技巧
Excel组合图表怎么做 Excel创建柱状图与折线组合图教程【图表】
抖音未来赚钱的新趋势 2025年值得关注的变现风口分析
Go Martini框架:动态服务解码后的图片内容
C++ vector二维数组定义_C++ vector of vector用法
c++如何解决菱形继承问题_c++虚继承与虚基类详解
Golang如何优雅处理error_Golang error处理最佳实践总结


lt;/div>
<a href="/ai/2294" class="aritcle_card_btn">
<span>查看详情</span>
<img src="/static/images/cardxiayige-3.png" alt="ChatCut">
</a>
</div>
<p>与观察者模式不同,发布者不直接通知订阅者,而是将消息推送给事件中心,由事件中心分发给所有订阅该事件的消费者。</p>
<font color="#000000">
<strong>核心角色:</strong>
<ul>
<li>Publisher:发布事件</li>
<li>Subscriber:订阅感兴趣的事件</li>
<li>Event Channel:负责事件的注册、触发和管理</li>
</ul>
</font>
<p><strong>代码示例:</strong></p>
```j*ascript
class EventCenter {
constructor() {
this.events = {};
}
// 订阅事件
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
// 发布事件
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(callback => callback(data));
}
}
// 取消订阅
off(event, callback) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
}
// 只监听一次
once(event, callback) {
const wrapper = (data) => {
callback(data);
this.off(event, wrapper);
};
this.on(event, wrapper);
}
}
// 使用示例
const eventBus = new EventCenter();
eventBus.on('news', (msg) => {
console.log('新闻订阅者:', msg);
});
eventBus.on('news', (msg) => {
console.log('另一位读者:', msg);
});
eventBus.on('weather', (info) => {
console.log('天气预报:', info);
});
eventBus.emit('news', '今天发生了重大事件!');
// 输出:
// 新闻订阅者: 今天发生了重大事件!
// 另一位读者: 今天发生了重大事件!
eventBus.emit('weather', '明天晴,气温25℃');
// 输出:天气预报: 明天晴,气温25℃