JavaScript 设计模式之发布-订阅模式(上)
什么是发布订阅模式?
发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在JavaScript开发中,我们一般用事件模型来替代传统的发布—订阅模式。
发布订阅模式的构成
最常见的发布订阅模式就是咱们DOM事件,仔细回想一下我们要给一个按钮,绑定一个事件,当我点击按钮的时候我要让他的颜色变了,并且页面弹出一个弹出框
我们分析一下这个流程
首先,我们得知道给哪个按钮的时候绑定事件,然后我们得知道触发事件以后需要干什么?
那么在这其中谁是发布者?
是DOM中的按钮,因为是在它身上绑定了事件,当我们点击按钮的时候它便像订阅者发布了这个消息
那么谁是订阅者?
是click事件,当点击按钮时,dom发布了一条消息,而事件订阅了它,所以当它被点击的时候,订阅者会接收到消息
简单例子
以售楼处售楼为例子,售楼处都有一个花名册,然后当卖房的时候会给花名册里面的人依次发短信
var salesOffices = {}; // 定义售楼处
salesOffices.clientList = []; // 缓存列表,存放订阅者的回调函数,也就是花名册
salesOffices.listen = function( fn ){ // 增加订阅者
this.clientList.push( fn ); // 订阅的消息添加进缓存列表,也就是把一个买房的放进花名册里面
};
salesOffices.trigger = function(){ // 发布消息
//依次查看花名册里面的人,看他们需要什么样的房
for( var i = 0, fn; fn = this.clientList[ i++ ]; ){
//然后发短信告诉他们
fn.apply( this, arguments ); // (2) // arguments 是发布消息时带上的参数
}
};
salesOffices.listen( function( price, squareMeter ){ // 小明订阅消息即小明有一个这样买房的需求,然后我就把它添加到花名册里面去,小明没有明确的买房具体要求
console.log( '价格= ' + price );
console.log( 'squareMeter= ' + squareMeter );
});
//售楼处发布了一个消息,有一个88平米,售价200万的房
salesOffices.trigger( 2000000, 88 ); // 输出:200万,88平方米
//发布完以后小明就收到了消息,这就是发布-订阅模式
现在大家大概都有点理解了什么是发布订阅模式了吧?
如果大家再不理解的话,我再举一个通俗的例子:
上大学的时候甲和乙要打游戏,下午的课不准备去了,然后甲跟丙说,如果下午老师问我去哪了,你就发信息告诉我,已跟丙说,如果下午老师问我去哪了,你就发信息告诉我。然后果然不出所料,下午老师来了,并且问了甲和已去哪了?然后丙发信息给甲和已了,甲和已收到信息后干什么丙不知道,丙只是负责如果老师问了就发短信给甲和已。
这样能听明白了吗?所以发布订阅设计模式要先订阅消息,然后再等到发布消息的时候就能触发事件
上面的例子是如果只要有房卖就告诉小明,什么消息都会告诉小明
现在小明只想要80平米的房子的消息,我们来优化一下
var salesOffices = {}; // 定义售楼处
salesOffices.clientList = {}; // 缓存列表,存放订阅者的回调函数
salesOffices.listen = function( key, fn ){
if ( !this.clientList[ key ] ){ // 如果还没有订阅过此类消息,给该类消息创建一个缓存列表
this.clientList[ key ] = [];
}
this.clientList[ key ].push( fn ); // 订阅的消息添加进消息缓存列表
};
salesOffices.trigger = function(){ // 发布消息
var key = Array.prototype.shift.call( arguments ), // 取出消息类型
fns = this.clientList[ key ]; // 取出该消息对应的回调函数集合
if ( !fns || fns.length === 0 ){ // 如果没有订阅该消息,则返回
return false;
}
for( var i = 0, fn; fn = fns[ i++ ]; ){
fn.apply( this, arguments ); // (2) // arguments是发布消息时附送的参数
}
};
salesOffices.listen( 'squareMeter88', function( price ){ // 小明订阅88平方米房子的消息
console.log( '价格= ' + price ); // 输出: 2000000
});
salesOffices.trigger( 'squareMeter88', 2000000 ); // 发布88平方米房子的价格,小明能收到
salesOffices.trigger( 'squareMeter110', 3000000 ); // 发布110平方米房子的价格,小明收不到
这就是一个比较常用的发布订阅的设计模式了,下一篇进行重点讲解,本篇先了解一下什么是发布订阅模式,也就是观察者模式
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。