GOF对观察者模式的定义:Observer的意图是定义对象之间的一种一(被观察者)对多(观察者)的关系,当一个对象的状态发生改变时,所有依赖它的对象得到通知,并且会自动更新自己。
从这段经典的定义中,可以推测下,观察者模式中的俩个对象各自应该拥有的特征
1,被观察者应该可以注册观察者,注销观察者。
2,持有对其注册的观察者。
3,当自身改变时,依赖于特性一,其可以通知对其注册的观察者。
4,观察者会自动更新自己。
5,被观察者应该是独立的,也就是说,观察者影响其并不会影响被观察者。
java与js的事件机制都可以说观察者模式的应用场景。
在java的世界中借助于
j ava.util.Observable
java.util.Observer
中这俩个类可以非常简便的实现观察者模式-(java的awt的事件机制在底层就是借助观察者模式实现的,这也可以算是搭建java世界中事件机制的支撑基础类了)
对于js的事件,譬如,在一个DOM元素(被观察者)上的单击事件,观察者(也就是在这个事件上的回调函数)会关注这个很特别的时刻,并且做出反应。
在写js的自定义事件之前,先看一下曾经令我十分好奇的EXT的自定义事件
部分代码来自 《深入浅出EXTJS》和《javascript高级程序设计》(第二版)
Person=function(name){
this.name=name;
this.addEvents('work','read');
};
Ext.extends(Person,Ext.util.Observable);
当自定义的类继承了Ext.util.Observable后,自定义的类便可以支持事件。
var sz=new Person('sz');
sz.on('work',function(){//为Person的实例绑定监听,即把观察者注册到要被观察者
Ext.Msg.alert('宋峥,在工作那!');
});
下面,来触发这个事件,其实原理很简单,就是让'work'事件对应处理函数执行。
sz.fireEvent('work');//回调函数执行
很神奇,其实这就是封装的力量,EXT对原生js的封装,让实现自定义事件变的如此简单。
来看看《javascript高级程序设计》(第二版)对是自定义事件的实现(有小改动)。
对EXT自定义的事件的实现的原理?是不是已经相当透彻了?是不是可以联系到观察者设计模式?
function Obserable(){
this.handlers={};//持有事件处理函数
}
Obserable.prototype={//重写EventTarget的原型对象
constructor:EventTarget,
on:function(type,handler){//对应于观察者模式-在相应的被观察者注册观察者
//handlers中是否已有针对此事件类型的数组
//没有创建一个空数组
//把这个处理函数推入对应的handlers[type]数组,
if(typeof this.handlers[type]=="undefined"){
this.handlers[type]=[];
}
this.handlers[type].push(handler);
},
fireEvent:function(event){
if(!event.target){
event.target=this;
}
if(this.handlers[event.type] instanceof Array){
var handlers=this.handlers[event.type];//检出被观察者注册的观察者
for(var i=0;len=handlers.length;i++){
handlers[i]();//回调函数执行,也就是观察者更新自己
}
}
}
};
function handlerMessage(event){
alert("处理函数被回调");
}
var ob=new Obserable();
ob.on('message',handlerMessage);
ob.fireEvent({type:'message'});
至此,只要继承了此Obserable类的相应类的实例都可以成为被观察者了,也就都可以支持事件了,这也就和EXT的自定义事件的思路没多大差异了,当然EXT的设计更加巧妙。越来越有看EXT源码的欲望了,但水平还不够,还需努力。
最后,不难发现,原生态的事件,是在某一个特殊时刻(单击,获得焦点等等)发生时,由游览器把这一特殊时刻的一些信息,譬如事件类型,和其他的一些必要信息封装成event对象,触发事件处理程序时把这个event对象作为实参传入,而我们自定义的事件,当然只能由我们自己触发,传入的实参event也是我们自己传入的(这个event,想封装什么就封装什么,需要什么就封装什么).
从这段经典的定义中,可以推测下,观察者模式中的俩个对象各自应该拥有的特征
1,被观察者应该可以注册观察者,注销观察者。
2,持有对其注册的观察者。
3,当自身改变时,依赖于特性一,其可以通知对其注册的观察者。
4,观察者会自动更新自己。
5,被观察者应该是独立的,也就是说,观察者影响其并不会影响被观察者。
java与js的事件机制都可以说观察者模式的应用场景。
在java的世界中借助于
j ava.util.Observable
java.util.Observer
中这俩个类可以非常简便的实现观察者模式-(java的awt的事件机制在底层就是借助观察者模式实现的,这也可以算是搭建java世界中事件机制的支撑基础类了)
对于js的事件,譬如,在一个DOM元素(被观察者)上的单击事件,观察者(也就是在这个事件上的回调函数)会关注这个很特别的时刻,并且做出反应。
在写js的自定义事件之前,先看一下曾经令我十分好奇的EXT的自定义事件
部分代码来自 《深入浅出EXTJS》和《javascript高级程序设计》(第二版)
Person=function(name){
this.name=name;
this.addEvents('work','read');
};
Ext.extends(Person,Ext.util.Observable);
当自定义的类继承了Ext.util.Observable后,自定义的类便可以支持事件。
var sz=new Person('sz');
sz.on('work',function(){//为Person的实例绑定监听,即把观察者注册到要被观察者
Ext.Msg.alert('宋峥,在工作那!');
});
下面,来触发这个事件,其实原理很简单,就是让'work'事件对应处理函数执行。
sz.fireEvent('work');//回调函数执行
很神奇,其实这就是封装的力量,EXT对原生js的封装,让实现自定义事件变的如此简单。
来看看《javascript高级程序设计》(第二版)对是自定义事件的实现(有小改动)。
对EXT自定义的事件的实现的原理?是不是已经相当透彻了?是不是可以联系到观察者设计模式?
function Obserable(){
this.handlers={};//持有事件处理函数
}
Obserable.prototype={//重写EventTarget的原型对象
constructor:EventTarget,
on:function(type,handler){//对应于观察者模式-在相应的被观察者注册观察者
//handlers中是否已有针对此事件类型的数组
//没有创建一个空数组
//把这个处理函数推入对应的handlers[type]数组,
if(typeof this.handlers[type]=="undefined"){
this.handlers[type]=[];
}
this.handlers[type].push(handler);
},
fireEvent:function(event){
if(!event.target){
event.target=this;
}
if(this.handlers[event.type] instanceof Array){
var handlers=this.handlers[event.type];//检出被观察者注册的观察者
for(var i=0;len=handlers.length;i++){
handlers[i]();//回调函数执行,也就是观察者更新自己
}
}
}
};
function handlerMessage(event){
alert("处理函数被回调");
}
var ob=new Obserable();
ob.on('message',handlerMessage);
ob.fireEvent({type:'message'});
至此,只要继承了此Obserable类的相应类的实例都可以成为被观察者了,也就都可以支持事件了,这也就和EXT的自定义事件的思路没多大差异了,当然EXT的设计更加巧妙。越来越有看EXT源码的欲望了,但水平还不够,还需努力。
最后,不难发现,原生态的事件,是在某一个特殊时刻(单击,获得焦点等等)发生时,由游览器把这一特殊时刻的一些信息,譬如事件类型,和其他的一些必要信息封装成event对象,触发事件处理程序时把这个event对象作为实参传入,而我们自定义的事件,当然只能由我们自己触发,传入的实参event也是我们自己传入的(这个event,想封装什么就封装什么,需要什么就封装什么).