JavaScript发布/订阅模式与观察者模式的区别及实现

作者:闭包旅人时间:2026-10-28 15:49:27浏览:649

本文解析JavaScript中发布/订阅模式与观察者模式的核心区别,指出前者通过消息通道解耦发布者和订阅者,后者依赖目标对象直接维护观察者列表。文章提供完整的JS发布/订阅模式代码示例,包括发布、订阅及触发逻辑,帮助开发者理解事件驱动架构下的解耦实现。

发布/订阅模式与观察者模式的区别

此前探讨观察者模式时,许多资料将其等同于Subscribe/Publish(发布/订阅模式)。然而,在《Javascript设计模式》一书中,这两种模式存在明确差异。书中指出:

1. Observer模式要求希望接收主题通知的观察者必须主动订阅内容变更事件。

2. Subscribe/Publish模式引入一个主题/事件通道,位于订阅者与发布者之间。该事件系统允许代码定义应用程序的特定事件,并可传递包含订阅者所需值的自定义参数。其核心目的是避免订阅者与发布者之间产生直接依赖。

与Observer模式的主要区别在于,它允许任何订阅者注册并接收发布者发出的通知,只要执行适当的事件处理程序即可。

尽管概念抽象,以下是我的理解:

1. 在观察者模式中,目标对象负责维护观察者列表;而在发布/订阅模式中,发布者不关心具体订阅者,仅负责发送消息。

2. 观察者模式中,观察者需提供统一接口(如update方法),当目标对象状态改变时调用该接口以同步状态。而在发布/订阅模式中,订阅者通过监听特定消息(包含名称及所需参数)来触发事件,而非依赖统一接口。订阅者监听的是消息池,只要池中存在关心的消息即触发事件,无论消息来源。这使得发布者和订阅者完全解耦。

JavaScript发布/订阅模式实现

以下是JavaScript中发布/订阅模式的实现代码,复制到控制台即可测试:

代码如下:

var pubsub = (function(){
var q = {}
topics = {},
subUid = -1;
//发布消息
q.publish = function(topic, args) {
if(!topics[topic]) {return;}
var subs = topics[topic],
len = subs.length;
while(len--) {
subs[len].func(topic, args);
        }
return this;
    };
//订阅事件
q.subscribe = function(topic, func) {
topics[topic] = topics[topic] ? topics[topic] : [];
var token = (++subUid).toString();
topics[topic].push({
token : token,
func : func
        });
return token;
    };
return q;
//取消订阅逻辑省略,需遍历topics并通过保存的token删除指定元素
})();
//触发的事件
var logmsg = function(topics, data) {
console.log("logging:" + topics + ":" + data);
}
//监听指定的消息'msgName'
var sub = pubsub.subscribe('msgName', logmsg);
//发布消息'msgName'
pubsub.publish('msgName', 'hello world');
//发布无人监听的消息'msgName1'
pubsub.publish('anotherMsgName', 'me too!');
作者最新文章