观察者模式(发布-订阅者模式)
定义了一种一对多的关系,多个观察者对象同时监听一个主题对象,当主题对象的状态发生变化时就会通知各个监听的观察者,以做出各自响应。
实现
首先需要将观察者对象创建出来,包括一个消息容器(消息队列),订阅消息方法,取消订阅消息方法,以及发送消息的方法。
基本机构如下:
// 使用闭包,可以防止消息队列暴露被篡改
var Observer = (function(){
var _messages = {}; // 消息队列
return {
// 订阅
regist: function(type, fn) {},
// 发布
publish: function(type, msg) {},
// 取消订阅
remove: function(type, fn) {}
};
})();
雏形出来了,接下来就是完成各个函数功能:
// 订阅
regist: function(type, fn) {
if (typeof _messages[type] !== 'undefined') {
_messages[type].push(fn);
} else {
_messages[type] = [fn];
}
}
// 发布
publish: function(type, msg) {
if (!_messages[type]) {
return;
}
for (let i = 0; i < _messages[type].length; i++) {
// _messages[type][i].call(this, msg);
_messages[type][i](msg);
}
}
// 取消订阅
remove: function(type, fn) {
if (_messages[type] instanceof Array) {
for (let i = _messages[type].length - 1; i >= 0; i--) {
_messages[type][i] === fn && _messages[type].splice(i, 1);
}
}
}
用ES6的类实现如下:
// ES6
class Observer {
constructor() {
this._messages = {}; // 消息队列
}
// 订阅
regist(type, fn) {
if (typeof this._messages[type] === 'undefined') {
this._messages[type] = [fn];
} else {
this._messages[type].push(fn);
}
}
// 发布
publish(type, msg) {
if (!this._messages[type]) {
return;
}
for (let fn of this._messages[type]) {
fn(msg);
}
}
// 取消订阅
remove(type, fn) {
if (this._messages[type] instanceof Array) {
for (let i = 0; i < this._messages[type].length; i++) {
this._messages[type][i] === fn && this._messages[type].splice(i, 1);
}
}
}
}
应用场景
观察者模式主要作用是解耦两个相互依赖的对象,使其依赖于观察者的消息机制,各个观察者之间互不影响。
适用于大型项目的开发中涉及多模块调用的需求,模块间的信息传递不再需要相互引用其他模块,只需要通过观察者模式注册或者发布消息即可。