Ext 源码学习之 Observal:类

本文详细介绍了Observable模式在Java设计中的实现原理及应用场景,包括事件监听的添加、触发过程,并通过一个具体的员工姓名更改示例展示了其实际操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  Observable故明思义,就是观察者的意思,主要是事件的处理,在java设计模式中,有观察者这一设计模式.观察者的主要思路是,对于某一事件发生变化,能对该事件的变化
做出相应的处理.用代码来来说就是增加事件侦听,和侦听的处理机制.
Observable类在定义时,代码如下:
if(this.listeners){
this.on(this.listeners);
delete this.listeners;
}


只是做了一个增加侦听的处理. on 是对方法 addListener 的定义.可以看一下 addListener方法做的事情:

addListener : function(eventName, fn, scope, o){
if(typeof eventName == "object"){
o = eventName;
for(var e in o){
if(this.filterOptRe.test(e)){
continue;
}
if(typeof o[e] == "function"){
// shared options
this.addListener(e, o[e], o.scope, o);
}else{
// individual options
this.addListener(e, o[e].fn, o[e].scope, o[e]);
}
}
return;
}
o = (!o || typeof o == "boolean") ? {} : o;
eventName = eventName.toLowerCase();
var ce = this.events[eventName] || true;
if(typeof ce == "boolean"){
ce = new Ext.util.Event(this, eventName);
this.events[eventName] = ce;
}
ce.addListener(fn, scope, o);
}


该方法主要定义事件,并增加侦听到对应的事件中.其中涉及到Event类.Event类如下:

Ext.util.Event = function(obj, name){
this.name = name;
this.obj = obj;
this.listeners = [];
};

先定义事件的名称,对象,侦听列表,对原型重载:

Ext.util.Event.prototype = {
addListener : function(fn, scope, options){
scope = scope || this.obj;
if(!this.isListening(fn, scope)){
var l = this.createListener(fn, scope, options);
if(!this.firing){
this.listeners.push(l);
}else{ // if we are currently firing this event, don't disturb the listener loop
this.listeners = this.listeners.slice(0);
this.listeners.push(l);
}
}
},

createListener : function(fn, scope, o){
o = o || {};
scope = scope || this.obj;
var l = {fn: fn, scope: scope, options: o};
var h = fn;
if(o.delay){
h = createDelayed(h, o, scope);
}
if(o.single){
h = createSingle(h, this, fn, scope);
}
if(o.buffer){
h = createBuffered(h, o, scope);
}
l.fireFn = h;
return l;
},

findListener : function(fn, scope){
scope = scope || this.obj;
var ls = this.listeners;
for(var i = 0, len = ls.length; i < len; i++){
var l = ls[i];
if(l.fn == fn && l.scope == scope){
return i;
}
}
return -1;
},

isListening : function(fn, scope){
return this.findListener(fn, scope) != -1;
},

removeListener : function(fn, scope){
var index;
if((index = this.findListener(fn, scope)) != -1){
if(!this.firing){
this.listeners.splice(index, 1);
}else{
this.listeners = this.listeners.slice(0);
this.listeners.splice(index, 1);
}
return true;
}
return false;
},

clearListeners : function(){
this.listeners = [];
},

fire : function(){
var ls = this.listeners, scope, len = ls.length;
if(len > 0){
this.firing = true;
var args = Array.prototype.slice.call(arguments, 0);
for(var i = 0; i < len; i++){
var l = ls[i];
if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
this.firing = false;
return false;
}
}
this.firing = false;
}
return true;
}
};


对原型重载:主要有增加侦听,创建侦听,查找侦听,判断侦听是否存在,删除侦听,清除所有侦听,触发侦听七个主要方法.
  增加侦听:先判断侦听是否存在,如果已存在则不处理,如果不存在,则创建侦听,如果末触发则增加,如果正在触发则取触发队列进行增加.

对于增加完侦听后,可以对事件侦听的触发,触发方法 fireEvent,其方法如下:

fireEvent : function(){
if(this.eventsSuspended !== true){
var ce = this.events[arguments[0].toLowerCase()];
if(typeof ce == "object"){
return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
}
}
return true;
}

传递两个参数,事件名称和数据.
现在有了事件和侦听,还可以触发事件,可以写个例子应用一下.一个给一个员工修改姓名时,这时将触发一个事件,通知已经修改员工姓名,并把员工新旧名列出.
//定义一个人类

person = function(name) {
person.superclass.constructor.call(arguments);
this.name = name;
this.addEvents("update");//增加侦听,可以放在外面处理
};


//扩展人类,让它继承Observable类

Ext.extend(person,Ext.util.Observable,{
setName:function(name){
this.name = name;
},
update : function(name){
if(this.hasListener("update")){
this.fireEvent("update",{newName:name,oldName:this.name});//更新时处理
}
this.name = name;
}
});

测试:

var p = new person("Jacky");

p.on("update", function(args) {
alert(JSON.stringify(args));
});

p.update("Andy");


这里可以看出触发了update的事件,而且可以针对一个事件,增加多个侦听.如可以再增加侦中:

p.on("update", function(args) {
alert("SHIT");
});

这样设置后,在触发完事件后执行第一个侦听后,会再执行另一个侦听.如果这里修改第一个侦听返回return false时,则不再往下执行其它侦听.可看源码中event事件的fire方法:

if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
this.firing = false;
return false;
}

对于一个简单的Observable类的继承设计的总结:首先是先注册一个事件,会把这个事件写入到Observable里的全局event来增加ext.util.event实例.完成后要进行实例的侦听.这个可以放在实例对象后进行处理.增加侦听时,只是对应的把这些函数,入参等信息增加到方法中.最后进行fire事件,在fire时把原来保存在event中(event只是一个{}).里面保存了fn,scope,option这些信息,在fire时找到对应的listener后,进行调用.


其它Observable相关方法:

Ext.util.Observable.capture 对原有事件的catch
Ext.util.Observable.capture(p,function(fn,option){
alert(JSON.stringify(option));
}) ;

在触发前调用该事件.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值