JavaScript设计模式之代理模式详解
代理模式是非常常见的模式,比如我们使用的VPN工具,明星的经纪人,都是代理模式的例子。但是,有人会疑问,明明可以直接访问对象,为什么中间还要加一个壳呢?这也就说到了代理模式的好处。在我看来,代理模式最大的好处,就是在不动原有对象的同时,可以给原有对象增加一些新的特性或者行为。
/** *pre:代理模式 *小明追求A,B是A的好朋友,小明比较腼腆,不好意思直接将花交给A, *于是小明将花交给B,再由B交给A. */ //-----------示例1--------- //不使用代理 varFlower=function(){}; varxiaoming={ sendFlower:function(target){ varflower=newFlower(); target.receiveFlower(flower); } }; varA={ receiveFlower:function(flower){ console.log("收到花:"+flower); } }; xiaoming.sendFlower(A); //-----------示例2-------------- //使用代理1 varFlower=function(){}; varxiaoming={ sendFlower:function(target){ varflower=newFlower(); B.receiveFlower(flower); } }; varB={ receiveFlower:function(flower){ A.receiveFlower(flower); } }; varA={ receiveFlower:function(flower){ console.log("收到花:"+flower); } }; xiaoming.sendFlower(B); //-------------示例3--------------- /* *使用代理2 *从示例1和示例2,看不出使用代理有什么用处,B只不过是从中间转手了一次。 *接下来,我们想一下。给喜欢的人送花,怎样才能提高成功率呢? *我们都知道,人有心情好和心情差的时候,当美女心情好的时候,送花成功的概率自然要大些。 *于是,我们将代理升级,监听美女的心情,心情好的时候再给她送花。 *为了演示,我们假设2秒后,A的心情变好。 */ varFlower=function(){}; varxiaoming={ sendFlower:function(target){ varflower=newFlower(); B.receiveFlower(flower); } }; varB={ receiveFlower:function(flower){ A.listenGoodMood(function(){ A.receiveFlower(flower); }); } }; varA={ receiveFlower:function(flower){ console.log("收到花:"+flower); }, listenGoodMood:function(fn){ setTimeout(function(){ fn.apply(this,arguments); },2000); } }; xiaoming.sendFlower(B); //----------示例4--------------- /* *【代理模式用处】:虚拟代理 *这里以加载图片为例,我们都知道当网络不畅以及图片过大时,图片加载都比较慢, *为了更好的用户体验,我们都会在原图片未加载完成前,加上loading图片。 **/ //--4_01未使用代理-- varmyImage=(function(){ varimgNode=document.createElement("img"); document.body.appendChild(imgNode); return{ setSrc:function(src){ this.imgNode.src=src; } } })(); myImage.setSrc("xxx"); //--4_02使用代理-- varproxyMyImage=(function(){ varimg=newImage(); img.onload=function(){ myImage.setSrc(this.src); }; return{ setSrc:function(src){ myImage.setSrc("loading.jpg"); img.src=src; } } })(); proxyMyImage.setSrc("xxx"); /* *[注]:这里可以看到代理模式的好处:在不改变原有接口的同时,可以为系统添加新的行为。 */ //---------示例5--------------- /* *【代理模式用处】:合并http请求 *这里以选择文件同步为例。 *以往用户同步文件,在用户选中的时候就触发,这种方法做到了实时性,但无疑增加了网络的开销。 *实际在使用的过程中,往往并不需要立刻就同步。 *以下通过代理模式,将在用户选中文件2秒后进行同步请求。 **/ //---包含一段html代码,请自行添加到一个文件中------点我上传 1 2 3 4 5 6 7 8 9 //--上传文件-- varsynchronizeFile=function(id){ console.log("开始同步文件:"+id); }; varproxySynchronizeFiles=(function(){ varfileCache=[], timer; returnfunction(id){ fileCache.push(id); if(timer){ return; } timer=setTimeout(function(){ synchronizeFile(fileCache.join(",")); clearTimeout(timer); timer=null; checkArr.length=0; },2000); } })(); varcheckArr=document.getElementsByTagName("input"); for(vari=0,c;c=checkArr[i++];){ c.onclick=function(){ if(this.checked==true){ proxySynchronizeFiles(this.id); } } } //------------示例6----------------- /* *【代理模式用处】:缓存代理 *以计算器为例,比如计算某些数的乘积,当参数重复时,我们希望不用重复计算,直接返回结果。 *以下用到代理模式做缓存。 */ varmult=function(){ if(!arguments){ console.log("请输入参数"); return; } vara=1; for(vari=0,b;b=arguments[i++];){ a=a*b; } returna; }; varproxyMult=(function(){ varcache={}; returnfunction(){ varstr=Array.prototype.join.call(arguments,","); if(strincache){ console.log("重复return."); returncache[str]; } returncache[str]=mult.apply(this,arguments); } })(); console.log(proxyMult(2,3,4)); console.log(proxyMult(2,3,4)); //------------示例7-------------- /* *缓存代理升级-通用版计算 * */ varmult=function(){ if(!arguments){ return; } vart=1; for(vari=0,a;a=arguments[i++];){ t=t*a; } returnt; }; varplus=function(){ if(!arguments){ return; } vart=0; for(varaofarguments){ t+=a; } returnt; }; varcreateProxyCaculate=function(fn){ varcache={}; returnfunction(){ varstr=Array.prototype.join.call(arguments,","); if(strincache){ console.log("重复return"+str); returncache[str]; } returncache[str]=fn.apply(this,arguments); } }; varproxyMult=createProxyCaculate(mult); varproxyPlus=createProxyCaculate(plus); console.log(proxyMult(2,3,4)); console.log(proxyMult(2,3,4));
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。