Javascript设计模式之观察者模式
首先说一下观察者模式的应用场景
观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。(Tom大叔)
具体说一下这个观察者模式,就是一个发报纸的过程。我们订阅了报纸,在报社的数组里加上我们的名字(不仅是名字了是一个带我们名字的处理函数),这是订阅事件;报社才不管你订没订报纸,他只管给他数组里的人发报纸;我们在编码的时候只监听发报纸的事件,订不订报纸,谁订报纸,都是你的事,就不在放在监听的事件里了,于是就有了减少监听的优化;
我们来构建一下观察者API
首先我们设置一个报社:
1 function Publisher(){ 2 this.subscribers = [];//报社存放关于订阅者的数组 3 }
下面实现报社发报纸:
1 Publisher.prototype.deliver = function(data) {//记住哦,发报纸是deliver方法,里面是报纸内容的参数 2 this.subscribers.forEach(function(fn){ 3 fn(data); 4 }) 5 return this; 6 };
好,下面是订阅方法,当然,所有人想订阅就订阅,方法加在Function的原型链上:
Function.prototype.subscribe = function(publisher){ var this = that; var alreadyExists = publisher.subscribers.some(function(el){ return el === that; }); if ( !alreadyExists) { publisher.subscribers.push(this); }; return this; }
数组的some方法,和foreach的回调形式差不多,不过只要有一次调用回调函数就会返回true否则为false;
退订方法:
Function.prototype.unsubscribe = function(publisher){ var this = that; publisher.subscribers = publisher.subscribers.filter(function(el){ return el !== that; }) return this; }
这里数组的filter方法,返回符合条件的数组,遍历数组,如果他的某一元素不等于这“我”,就返回其他。相当于数组的shift(“我”)方法;
至此API完了。这玩意怎么用呢。
举一个动画的例子;
var Animation = function(o){ this.onStart = new Publisher, this.onComplete = new Publisher, this.onTween = new Publisher; }; Animation.prototype.fly = funciton(){ this.onStart.deliver(); for(...){//这里遍历所有的组织 this.onTween.deliver(i); } this.onComplete.deliver(); } var Superman = new Animation({})//设置特性 var pushOnCape = function(i){};//这里添加处理事件 var takeOfCape = function(i){};//这里添加处理事件 pushOnCape.subscribe(Superman.onStart); takeOfCape.subscribe(Superman.onComplete); //然后,这个fly写哪都行 $('div').addEventListener('click',function(){ Superman.fly(); })
说明:
这里监听一个click,让报社发报纸。发给谁用谁订阅。比如pushOnCape、和takeOfCape都
调用了subscribe方法,加入一个事件就让他订阅就行;
这里的subscribe方法传递一个onStart相当于start报社,还有另外两家报社,他们分别发自己的报纸,想订谁的
报纸就订阅哪家的报社;
当点击div的时候。调用了fly方法,各个报社开始发自己的报纸(deliver),报社查看自己的订阅者数组[],发现
pushOnCape、takeOfCape调用过subscribe方法,加入到数组了,就给他发消息了;消息是data,这里没啥用,不过
this.onTween.deliver(i);这里可以区分i,主要是发送消息到他自己,这里是pushOnCape、takeOfCape,于是调用它们自己的函数
function(i){}如注释,->这里添加处理事件,其实是触发click的时候各个部分进行的动作;
总结一下:
观察者模式的作用就是将各种行为和信息都给他的自己,用subscribe方法来做,削减监听器的数量,减低内存消耗,
提高互动性能;
它的坏处就是创建可观察对象带来的时间消耗,不过你可以在用它的时候再实例化它,程序初始化的时候就不会有影响;
首先说一下观察者模式的应用场景
观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。(Tom大叔)
具体说一下这个观察者模式,就是一个发报纸的过程。我们订阅了报纸,在报社的数组里加上我们的名字(不仅是名字了是一个带我们名字的处理函数),这是订阅事件;报社才不管你订没订报纸,他只管给他数组里的人发报纸;我们在编码的时候只监听发报纸的事件,订不订报纸,谁订报纸,都是你的事,就不在放在监听的事件里了,于是就有了减少监听的优化;
我们来构建一下观察者API
首先我们设置一个报社:
function Publisher(){
this.subscribers = [];//报社存放关于订阅者的数组
}
下面实现报社发报纸:
Publisher.prototype.deliver = function(data) {//记住哦,发报纸是deliver方法,里面是报纸内容的参数
this.subscribers.forEach(function(fn){
fn(data);
})
return this;
};
给基础不好的同学讲一下,forEach传递两个参数得时候第一个参数是数组内容,第二个参数是index,这里的fn是
代表数组里“我”的处理;我还为怎么传进来fn纠结了一阵,是被匿名函数蒙蔽了双眼;返回this,让他能够连续调用,能
连续不断的投送数据;
好,下面是订阅方法,当然,所有人想订阅就订阅,方法加在Function的原型链上:
Function.prototype.subscribe = function(publisher){
var this = that;
var alreadyExists = publisher.subscribers.some(function(el){
return el === that;
});
if ( !alreadyExists) {
publisher.subscribers.push(this);
};
return this;
}
数组的some方法,和foreach的回调形式差不多,不过只要有一次调用回调函数就会返回true否则为false;
退订方法:
Function.prototype.unsubscribe = function(publisher){
var this = that;
publisher.subscribers = publisher.subscribers.filter(function(el){
return el !== that;
})
return this;
}
这里数组的filter方法,返回符合条件的数组,遍历数组,如果他的某一元素不等于这“我”,就返回其他。相当于数组的shift(“我”)方法;
至此API完了。这玩意怎么用呢。
举一个动画的例子;
var Animation = function(o){
this.onStart = new Publisher,
this.onComplete = new Publisher,
this.onTween = new Publisher;
};
Animation.prototype.fly = funciton(){
this.onStart.deliver();
for(...){//这里遍历所有的组织
this.onTween.deliver(i);
}
this.onComplete.deliver();
}
var Superman = new Animation({})//设置特性
var pushOnCape = function(i){};//这里添加处理事件
var takeOfCape = function(i){};//这里添加处理事件
pushOnCape.subscribe(Superman.onStart);
takeOfCape.subscribe(Superman.onComplete);
然后,这个fly写哪都行
$('div').addEventListener('click',function(){
Superman.fly();
})
说明:
这里监听一个click,让报社发报纸。发给谁用谁订阅。比如pushOnCape、和takeOfCape都
调用了subscribe方法,加入一个事件就让他订阅就行;
这里的subscribe方法传递一个onStart相当于start报社,还有另外两家报社,他们分别发自己的报纸,想订谁的
报纸就订阅哪家的报社;
当点击div的时候。调用了fly方法,各个报社开始发自己的报纸(deliver),报社查看自己的订阅者数组[],发现
pushOnCape、takeOfCape调用过subscribe方法,加入到数组了,就给他发消息了;消息是data,这里没啥用,不过
this.onTween.deliver(i);这里可以区分i,主要是发送消息到他自己,这里是pushOnCape、takeOfCape,于是调用它们自己的函数
function(i){}如注释,->这里添加处理事件,其实是触发click的时候各个部分进行的动作;
总结一下:
观察者模式的作用就是将各种行为和信息都给他的自己,用subscribe方法来做,削减监听器的数量,减低内存消耗,
提高互动性能;
它的坏处就是创建可观察对象带来的时间消耗,不过你可以在用它的时候再实例化它,程序初始化的时候就不会有影响;