手机版

深度理解JavaScript系列(31):设计模式的代理模式详解

时间:2021-10-13 来源:互联网 编辑:宝哥软件园 浏览:

介绍

代理,顾名思义,就是帮助别人做事。GoF对代理模式的定义如下:

代理模式为其他对象提供代理,以控制对此对象的访问。

代理模式使代理对象能够控制具体对象的引用。代理几乎可以是任何对象:文件、资源、内存中的对象或难以复制的东西。

主体

让我们举一个简单的例子。如果嘟嘟想送玫瑰给她的酸奶妹妹,但是她不知道自己的联系方式或者不好意思,想委托叔叔送这些玫瑰,那么她的叔叔就是代理人(其实挺好的,可以送一些玫瑰给儿媳妇)。我们怎么做?复制代码如下://首先声明美颜对象var girl=function (name) {this。name=name};

//这是DuDu var DuDu=function(girl){ this。女生=女生;这个。send gift=function(gift){ alert(' hi ' girl。名’,都都送你一份礼物:‘礼物’;}};

//大叔是代理var代理Tom=function(少女){this。女生=女生;this . send gift=function(gift){(new DuDu(girl))。sendGift(礼物);//为嘟嘟送花} };

调用方法很简单:复制代码如下: varproxy=new proxy Tom(new girl('酸奶女孩'));送礼物(' 999朵玫瑰');

实战中打。

通过上面的代码,相信大家对代理模式已经有了非常清晰的认识。让我们来一场真正的战斗:我们有一个简单的播放列表,我们需要在单击它时在单个连接(或全选)下方显示视频歌曲介绍和播放按钮,在单击播放按钮时播放视频。列表结构如下:复制代码如下: h1 deve Matthews vids/h1 pspan id=' toggle-all '全选/取消全选/span/pol id=' vids ' Li input type=' checkbox ' checkeda href=' http://new . music . Yahoo.com/videos/-2158073 ' gravediger/a/Li Li input type=' checkbox ' checkeda href=' http://new . music . Yahoo.com/videos/-4773

我们来分析一下:首先,我们不仅要监控连接A的点击事件,还要监控“全选/取消全选”的点击事件,然后请求服务器查询视频信息,并组装HTML信息显示在li元素的最后位置。效果如下:

然后监控播放连接的点击事件,点击后开始播放。效果如下:

好的,首先在没有jQuery的情况下,我们会自定义一个选择器:复制代码如下: var $=function(id){ return document . getelementbyid(id);};雅虎的json服务提供回调参数,所以我们导入定制的回调来接受数据。具体查询字符串汇编代码如下:复制代码如下: var HTTP={ Make Request 3360 function(IDS,回调){ var URL=' http://query . Yahoo API.com/v1/public/yql?q=',sql='从music.video.id中选择*其中ids IN ('%ID% ')',format='format=json ',handler='callback=' callback,script=document . createelement(' script ');

sql=sql.replace('%ID% ',ids.join(',' '));SQL=encodeURIComponent(SQL);

url=sql ''格式' '处理程序;script.src=url

document.body.appendChild(脚本);}};

代理如下:复制代码代码如下: varproxy={ids: [],delay: 50,超时: null,回调3360 null,上下文: null。//设置请求的id和回调,以触发回调makerequest:function (id,回调,context) {。

//添加到队列dd到队列this . ids . push(id);

this.callback=回调;this.context=context

//设置超时if(!这个。暂停){这。time out=setTimeout(function(){ proxy。flush();},这个。延迟);} }, //触发请求,使用代理职责调用了http.makeRequest flush:函数(){ //proxy.handler为请求美国美国yahoo公司公司时的回调http.makeRequest(this.ids,' proxy。处理程序');//请求数据以后,紧接着执行代理。处理者方法(里面有另一个设置的回调)//清楚超时和队列this.timeout=nullthis。ids=[];

},手柄:函数(数据){ var i,max

//单个视频的回收调用if (parseInt(data.query.count,10)=1){ proxy。回调。调用(代理。上下文,数据。查询。结果。视频);返回;}

//多个视频的回收调用for (i=0,max=数据。查询。结果。视频。长度;我最大;I=1){代理。回调。调用(代理。上下文,数据。查询。结果。视频[I]);} }};

视频处理模块主要有3种子功能:获取信息、展示信息、播放视频:

复制代码代码如下:var视频={ //初始化播放器代码,开始播放getPlayer:函数(id) { return ' ' '对象宽度='400 '高度=' 255 ' id=' uvp _ fop ' allowulscreen=' true ' ' ' param name=' movie ' value=' http://d。伊姆。com/m/up/fop/embeddflv/swf/fop。swf ' \/' param name=' flashVars ' value=' id=v ' id ' EId=1301797 lang=usenablefull },//拼接信息显示内容,然后在附加到里的底部里显示更新列表:函数(数据){ var id,html=' ',info

if(数据。查询){ data=data。查询。结果。视频;} id=data . idhtml=' img src=' http : '数据。图像[0]。url“”宽度=' 50 ' \/';html=' H2 '数据。标题“\/H2”;html='p' data.copyrightYear ',' data。标签“\/p”;如果(数据。相册){ html='pAlbum: '数据。专辑。发行。标题' ',数据。专辑。发布发布年份' br \/';} html=' pa class=' play ' href=' http://new。音乐。雅虎。com/video/-' id ' play \/a \/p ';info=文档。创建元素(' div ');info . id=' info ' idinfo . innerhtml=html $(" v " id).appendChild(信息);}, //获取信息并显示getInfo:函数(id){ var info=$(' info ' id);

if(!info) { proxy.makeRequest(id,videos.updateList,videos);//执行代理职责,并传入videos.updateList回调函数返回;}

if(信息。风格。display===' none '){ info。风格。display=} else { info。风格。显示='无';} }};

现在可以处理点击事件的代码了,由于有很多a连接,如果每个连接都绑定事件的话,显然性能会有问题,所以我们将事件绑定在开环(同开环)元素上,然后检测点击的是否是a连接,如果是说明我们点击的是视频地址,然后就可以播放了:

复制代码代码如下:美元(“视频”).onclick=function (e) { var src,id;

e=e | | window . event src=e . target | | e . Sr element;

//不是连接的话就不继续处理了if (src.nodeName.toUpperCase()!==' A '){ return;} //停止冒泡if(类型为e . prevent default==' function '){ e . prevent default();} e.returnValue=false

id=src。href。split('-')[1];

//如果点击的是已经生产的视频信息区域的连接玩吧,就开始播放//然后返回不继续了if(src。类名==' play '){ src。父节点。innerhtml=视频。get player(id);返回;} src。ParentNode。id=' v ' id视频。getinfo(id);//这个才是第一次点击的时候显示视频信息的处理代码};

全选反选的代码大同小异,我们就不解释了:

复制代码代码如下:$("切换所有")。onclick=函数(e){ 0

var hrefs,I,max,id;

hrefs=$('vids ')。getElementsByTagName(' a ');for (i=0,max=hrefs.length我最大;I=1) {//忽略播放连接if (hrefs [I]。播放'){继续;}//如果(!href[I]. parent node . first child . checked){ continue;}

id=href[I]. href . split('-')[1];href[I]. ParentNode . id=' v ' id;videos . Getinfo(id);}};

摘要

代理模式通常适用于以下情况:

1.远程代理是在不同的地址空间中为一个对象提供本地表示,可以隐藏一个对象存在于不同地址空间的事实,就像web服务中的代理类一样。2.虚拟代理,根据需要创建昂贵的对象,并存储需要长时间实例化的真实对象。例如在渲染浏览器时,首先显示问题,而图片可以缓慢显示(即真实图片被虚拟代理替换,此时虚拟代理保存真实图片的路径和大小。3.安全代理用于控制真实对象的访问权限,通常用于应该具有不同访问权限的对象。4.智能引导,只有当真正的对象被调用时,代理才处理其他事情。比如C#中的垃圾收集,在使用一个对象时,会有引用次数。如果对象没有被引用,垃圾回收器可以回收它。

参考:《大话设计模式》。

版权声明:深度理解JavaScript系列(31):设计模式的代理模式详解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。