代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。它的用处就是当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问。通俗来讲就是,代理是一个中间人,负责在客户和卖家之间传递信息,将没用的信息过滤,将有利于交易成功的信息传递给卖家,从而加大交易的成功率。
现在我们来通过一个小明给女神送花的例子来实现代理模式。
没有使用代理模式
let flower = function () {}; let xiaomingfirst = { ndflower ( target ) { let flower = new flower(); target.receiveflower( flower ); } } let a = { receiveflower ( flower ) { console.log('收到花') } } xiaomingfirst.ndflower(a);
使用代理模式重构
设定一个需求:aa为小明的女神,aa在心情好的时候接受小明花的几率更大,而b是aa和小明的好朋友,因此小明将花送给b,让b在aa心情好时转告自己的心意。
分析:重构后的代码增加了一个新的对象b ,此时b为aa的代理,b监听aa的好心情,代码中假定5秒后aa心情变好,b将花送出。
let xiaomingncend = { ndflower ( target ) { let flower = new flower(); target.receiveflower( flower ); } } let aa = { receiveflower () { console.log('收到花'); }, lis给男友一大段暖心的话tengoodmood ( fn ) { 冬奥会志愿者招募 ttimeout(()=>{ fn(); }, 5000); } } let b = { receiveflower ( flower ) { aa.listengoodmood( ()=>{ aa.receiveflower( flower ); } ); } } xiaomingncend.ndflower(b);
上述代码中代理模式可能显得不那么重要,但是体现了代理的思想,假如女神有一些要求,给他送花的男生必须帅而有钱,但又不能显得那么势力,因此代理可以帮其过滤掉这些不符合要求的男生,减少自己的许多麻烦,还能保持自己的美好形象这就是代理的用处。再者说,买一朵花很昂贵,而不是单单new这么简单,男生不想浪费自己的钱,因此想先确定女神是否接受自己的花,便让代理帮忙询问,如果女神接受则让代理帮忙买一朵送给女神,这样减少了男生的损失但也达成了目的,这便引出了以下两种代理模式。
保护代理:本体的要求直接在代理中实现,过滤掉不符合的要求的访问者对本体的请求虚拟代理:将一些开销很大的操作等到准备向本体请求时候再实现(主要用于实际开发)1. 虚拟代理实现图片预加载
分析:先加载本地图片,然后开始发起请求获取图片,当图片加载获取成功后,再调用myimage将图片替换预加载时显示的图片。
let myimage = function () { let img = document.createelement('img'); document.body.appendchild(img); return { tsrc ( src ) { 大枣的吃法 img.src = src; } } }(); proxyimage = function () { let img = new image; img.onload = function () { myimage.tsrc( this.src ); } return { tproxyimage( src ) { myimage.tsrc("/d/file/titlepic/01e2115d5d5c7da80120695c137bfb.jpg@1280w_1l_2o_100sh.jpg"); // 此处为加载 loading 图片,用来占位,本地图片(作者使用网络图片) img.src = src; } } }(); proxyimage.tproxyimage("/d/file/titlepic/prepstrong2.jpg 缓存代理分析:在代理中将本体计算的结果进行缓存,如果下次再遇到同样的请求,直接从缓存中获取,减少对本体的访问,减少性能消耗。
// 计算乘积的函数 let mult = function (...arg) { console.log('我执行了') let m = 1; for(let i = 0,l = arg.length; i <l; i++){ m *= arg[i]; } return m; } // 缓存代理 let proxymult = function( fn ) { let cache = {}; return function (...arg) { let args = arg.join(','); if( cache[args] ) { return cache[args]; } return cache[args] = fn.apply( this, arg); } }; let proxymult = proxymult(mult); console.log(proxymult(1,2,4))3. 虚拟代理合并 http 请求
小学生发言稿使用场景:点击复选框向服务器发起请求同步文件,每次点击复选框便发起一次请求,造成巨大网络开销,此时我们优化的方式为,将想同步的文件缓存下来,在 3 秒后通过一次请求发送到服务器。
<input type="checkbox" >1 <input type="checkbox" >2 <input type="checkbox" >3 <input type="checkbox" >4 <input type="checkbox" >5 <input type="checkbox" >6 <input type="checkbox" >7 <input type="checkbox" >8 <script> // 同步文件 let synchronousfile = function ( id ) { console.log("开始同步文件" + id); } // 代理实现同步文件 let proxysynchronousfile = function ( ) { let cache = []; let time; return function ( id ) { cache.push( id ); if( time ) { return; } time = tinterval(() => { synchronousfile(cache.join(',')); clearinterval(time); time = null; cache.length = 0; }, 3000); } }() // 添加点击执行 let checkboxlist = document.getelementsbytagname('input'); for(let i = 0, l = checkboxlist.length; i < l; i++) { checkboxlist[i].onclick = function() { if( this.checked === true ) { proxysynchronousfile(i+1); } } }五. 代理的使用意义及要求
意义:首先我们引入面向对象设先令计原则,单一职责原则,一个对象应该尽可能少的承担职责,最好是一个,如果承担职责过多,会提高代码的耦合度,从而导致脆弱和低内聚的设计。当变化发生,设计可能遭到意外破坏,即使实现同样需求可以将代码封装到一个函数中,但是最好的处理措施是引入代理模式
要求:代理和本体接口要一致,在任何使用本体地方都可以用代理来代替
六. 总结
代理模式包括很多小模块,最常用的为缓存代理和虚拟代理,虽然代理模式非常有用,但我们再编写业务代码时不需要预先猜测是否需要使用代理模式,到发现不方便直接访问某个对象,真正使用时再编写也不迟。
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注www.887551.com的更多内容!
本文发布于:2023-04-04 14:06:57,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/286621e615e08ea95f80b6db09c8e091.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:javascript设计模式之订阅者模式.doc
本文 PDF 下载地址:javascript设计模式之订阅者模式.pdf
留言与评论(共有 0 条评论) |