首先举一个现实生活中的例子:小区门口有一家商店,每天都会有很多小区里的人来商店买烟( 不提倡吸烟哦,只是举个例子? ),那刚好昨天卖完了,老板去进货,也不知道什么时候回来,那售货员这时一般都会把每一个客人的电话或者微信留下来,等老板把烟进回来后,售货员再通过记录的联系方式告诉每一个客人:“货到了,来买吧”。
那这就是一个观察者模式,即使是售货员辞职了,来了新的售货员也没有关系,依然是等到烟到了的时候,去通知每一位客人。
下面来模拟一下这个过程
var shop = {}; // 定义商店
shop.clientList = []; // 存储顾客联系方式的列表
shop.listen = function( fn ) { // 记录顾客联系方式
this.clientList.push( fn );
}
shop.goodsArrive = function() { // 货到了,通知留下联系方式的每一个顾客
for(let i = 0; i < this.clientList.length; i++) {
let fn = this.clientList[ i ];
fn.apply( this, arguments );
}
}
// 小明,小张,小李 都留下了联系方式
shop.listen(function(){
console.log( '我是小明,售货员告诉我,烟到了。' );
});
shop.listen(function(){
console.log( '我是小张,售货员告诉我,烟到了。' );
});
shop.listen(function(){
console.log( '我是小李,售货员告诉我,烟到了。' );
});
// 货到了,告知顾客
shop.goodsArrive();
// 我是小明,售货员告诉我,烟到了。
// 我是小张,售货员告诉我,烟到了。
// 我是小李,售货员告诉我,烟到了。
那如果在真实开发过程中,我们有两家店、三家店、甚至是一百、一千家店,那岂不是要写一千遍上面的代码,所以我们就想到了模块化,把这种设计模式封装成一个公用的模块,哪块的业务需求需要使用这种模式那就直接注册一下就好了。
下面我们写一个对象用来存放这种模式需要的基本参数和方法,再写一个给其他对象注册这种模式的函数:
var observer = {
clientList: [], // 存放订阅对象的列表
listenEvent: function( eventName, fn ) {
if (!this.clientList[ eventName ]) {
this.clientList[ eventName ] = [];
}
this.clientList[ eventName ].push( fn ); // 订阅的事件加到订阅对象列表中
},
sendEvent: function() {
let eventName = Array.prototype.shift.call( arguments ),
fns = this.clientList[ eventName ];
if (!fns || fns.length === 0) {
return false;
}
for (let i = 0; i < fns.length; i++) { // 发送事件给订阅该事件的对象
let fn = fns[ i ];
fn.apply( this, arguments );
}
}
};
var installObserver = function( obj ) { // 给obj注册观察者模式
for (var i in observer) {
obj[i] = observer[i];
}
}
var shop = {}; // 定义商店
installObserver( shop ); // 给商店注册观察者模式
shop.listenEvent( 'buySmoke', function(){ // 订阅buySmoke事件
console.log( '等烟到了,告诉我一声' );
});
shop.sendEvent( 'buySmoke' ); // 等烟到了,告诉我一声