在网上看到了有些同志提到了为Ajax的XMLHttpRequest提供一个对象池,也读了他们给出的实现代码。感觉不是特别理想,于是模仿apache的commons中的ObjectPool的思路写了一个简单的JavaScript版。
望指教:
代码
functionObjectPool(poolableObjectFactory){
this._poolableObjectFactory=poolableObjectFactory;
this._idlePool=[];
this._activePool=[];
}
//从对象池中租借一个对象,如果目前没有可用的空闲对象则通过poolableObjectFactory创建一个
//既然是借的,用完记得一定要还哦!
ObjectPool.prototype.borrowObject=function(){
varobject=null;
varidlePool=this._idlePool;
varfactory=this._poolableObjectFactory;
if(idlePool.length>0){
object=idlePool.pop();
}
else{
object=factory.makeObject();
}
if(object!=null){
this._activePool.push(object);
if(factory.activateObject){
factory.activateObject(object);
}
}
returnobject;
}
//归还一个对象
ObjectPool.prototype.returnObject=function(object){
functionindexOf(array,object){
for(vari=0;i
}
return-1;
}
if(object!=null){
varactivePool=this._activePool;
varfactory=this._poolableObjectFactory;
vari=indexOf(activePool,object);
if(i<0)return;
if(factory.passivateObject){
factory.passivateObject(object);
}
activePool.splice(i,1);
this._idlePool.push(object);
}
}
//返回当前激活对象的个数
ObjectPool.prototype.getNumActive=function(){
returnthis._activePool.length;
}
//返回当前空闲对象的个数
ObjectPool.prototype.getNumIdle=function(){
returnthis._idlePool.length;
}
//销毁对象池及其中的所有对象
//如果对象池中的对象需要析构。那么必须实现poolableObjectFactory中的destroyObject方法,同时保证ObjectPool的destroy方法在需要的时候被调用到(例如Window的unload事件中)。
ObjectPool.prototype.destroy=function(){
varfactory=this._poolableObjectFactory;
functionreturnObject(object){
if(factory.passivateObject){
factory.passivateObject(object);
}
}
functiondestroyObject(object){
if(factory.destroyObject){
factory.destroyObject(object);
}
}
varactivePool=this._activePool;
for(vari=0;i
returnObject(object);
destroyObject(object);
}
varidlePool=this._idlePool;
for(vari=0;i
destroyObject(object);
}
this._idlePool=null;
this._activePool=null;
this._poolableObjectFactory=null;
}
上面代码中ObjectPool的构造参数poolableObjectFactory的声明如下:
代码
//注意:这只是说明,不是真正的代码!
varPoolableObjectFactory={
makeObject:function(){},//创建一个新的对象。(必须声明)
activateObject:function(object){},//当一个对象被激活时(即被借出时)触发的方法。(可选)
passivateObject:function(object){},//当一个对象被钝化时(即被归还时)触发的方法。(可选)
destroyObject:function(object){}//销毁一个对象。(可选)
};
结合XMLHttpRequest创建过程的简陋示例:
代码
//声明XMLHttpRequest的创建工厂
varfactory={
makeObject:function(){
//创建XMLHttpRequset对象
//注:这里的创建方法不够强壮,勿学!
if(window.ActiveXObject){
returnnewActiveXObject("Microsoft.XMLHTTP");
}
else{
returnnewXMLHttpRequest();
}
},
passivateObject:function(xhr){
//重置XMLHttpRequset对象
xhr.onreadystatechange={};
xhr.abort();
}
};
varpool=newObjectPool(factory);//创建对象池
//......
varxhr=pool.borrowObject();//获得一个XMLHttpRequest对象
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
//......
pool.returnObject(xhr);//归还XMLHttpRequest对象
}
};
xhr.open(method,url,true);
//......
最后附上jsUnit的测试用例:
代码
functiontest_pool(){
varfactory={
counter:0,
makeObject:function(){
return{id:++this.counter};
},
activateObject:function(object){
object.activated=true;
},
passivateObject:function(object){
object.activated=false;
},
destroyObject:function(object){
object.destroyed=true;
}
};
varpool=newObjectPool(factory);
//borrowObjectobject1
varobject1=pool.borrowObject();
assertEquals(object1.id,1);
assertTrue(object1.activated);
assertEquals(factory.counter,1);
assertEquals(pool.getNumActive(),1);
assertEquals(pool.getNumIdle(),0);
//borrowObjectobject2
varobject2=pool.borrowObject();
assertEquals(object2.id,2);
assertTrue(object2.activated);
assertEquals(factory.counter,2);
assertEquals(pool.getNumActive(),2);
assertEquals(pool.getNumIdle(),0);
//borrowObjectobject3
varobject3=pool.borrowObject();
assertEquals(object3.id,3);
assertTrue(object3.activated);
assertEquals(factory.counter,3);
assertEquals(pool.getNumActive(),3);
assertEquals(pool.getNumIdle(),0);
//returnObjectobject2
pool.returnObject(object2);
assertFalse(object2.activated);
assertEquals(factory.counter,3);
assertEquals(pool.getNumActive(),2);
assertEquals(pool.getNumIdle(),1);
//returnObjectobject3
pool.returnObject(object3);
assertFalse(object3.activated);
assertEquals(pool.getNumActive(),1);
assertEquals(pool.getNumIdle(),2);
//returnObjectobject1
pool.returnObject(object1);
assertFalse(object1.activated);
assertEquals(pool.getNumActive(),0);
assertEquals(pool.getNumIdle(),3);
//destroythepool
pool.destroy();
assertTrue(object1.destroyed);
assertTrue(object2.destroyed);
assertTrue(object3.destroyed);
}