javascript设计模式之代理模式

这篇文章主要为大家介绍了javascript代理模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

一. 初识代理模式

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。它的用处就是当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问。通俗来讲就是,代理是一个中间人,负责在客户和卖家之间传递信息,将没用的信息过滤,将有利于交易成功的信息传递给卖家,从而加大交易的成功率。

二. 代理模式的实现思想

现在我们来通过一个小明给女神送花的例子来实现代理模式。

没有使用代理模式

        let Flower = function () {}; let xiaomingFirst = { sendFlower ( target ) { let flower = new Flower(); target.receiveFlower( flower ); } } let A = { receiveFlower ( flower ) { console.log('收到花') } } xiaomingFirst.sendFlower(A);

使用代理模式重构

设定一个需求AA 为小明的女神,AA 在心情好的时候接受小明花的几率更大,而 B 是 AA 和小明的好朋友,因此小明将花送给 B,让 B 在 AA 心情好时转告自己的心意。

分析:重构后的代码增加了一个新的对象 B , 此时 为 AA 的代理,监听 AA 的好心情,代码中假定5秒后 AA 心情变好,将花送出。

        let xiaomingSencend = { sendFlower ( target ) { let flower = new Flower(); target.receiveFlower( flower ); } } let AA = { receiveFlower () { console.log('收到花'); }, listenGoodMood ( fn ) { setTimeout(()=>{ fn(); }, 5000); } } let B = { receiveFlower ( flower ) { AA.listenGoodMood( ()=>{ AA.receiveFlower( flower ); } ); } } xiaomingSencend.sendFlower(B);

三. 代理模式分类

上述代码中代理模式可能显得不那么重要,但是体现了代理的思想,假如女神有一些要求,给他送花的男生必须帅而有钱,但又不能显得那么势力,因此代理可以帮其过滤掉这些不符合要求的男生,减少自己的许多麻烦,还能保持自己的美好形象这就是代理的用处。再者说,买一朵花很昂贵,而不是单单 new 这么简单,男生不想浪费自己的钱,因此想先确定女神是否接受自己的花,便让代理帮忙询问,如果女神接受则让代理帮忙买一朵送给女神,这样减少了男生的损失但也达成了目的,这便引出了以下两种代理模式。

  • 保护代理:本体的要求直接在代理中实现,过滤掉不符合的要求的访问者对本体的请求
  • 虚拟代理:将一些开销很大的操作等到准备向本体请求时候再实现(主要用于实际开发)

四. 虚拟代理模式的实际运用

1. 虚拟代理实现图片预加载

分析:先加载本地图片,然后开始发起请求获取图片,当图片加载获取成功后,再调用 myImage 将图片替换预加载时显示的图片。

    let myImage = function () { let img = document.createElement('img'); document.body.appendChild(img); return { setSrc ( src ) { img.src = src; } } }(); proxyImage = function () { let img = new Image; img.onload = function () { myImage.setSrc( this.src ); } return { setProxyImage( src ) { myImage.setSrc("https://img.zcool.cn/community/01e2115d5d5c7da80120695c137bfb.jpg-600@1280w_1l_2o_100sh.jpg-600"); // 此处为加载 loading 图片,用来占位,本地图片(作者使用网络图片) img.src = src; } } }(); proxyImage.setProxyImage("https://img.zcool.cn/community/01a5d45543cd170000019ae94fc087.jpg-600@1280w_1l_2o_100sh.jpg-600");

 2. 缓存代理

分析:在代理中将本体计算的结果进行缓存,如果下次再遇到同样的请求,直接从缓存中获取,减少对本体的访问,减少性能消耗。

    let myImage = function () { let img = document.createElement('img'); document.body.appendChild(img); return { setSrc ( src ) { img.src = src; } } }(); proxyImage = function () { let img = new Image; img.onload = function () { myImage.setSrc( this.src ); } return { setProxyImage( src ) { myImage.setSrc("https://img.zcool.cn/community/01e2115d5d5c7da80120695c137bfb.jpg-600@1280w_1l_2o_100sh.jpg-600"); // 此处为加载 loading 图片,用来占位,本地图片(作者使用网络图片) img.src = src; } } }(); proxyImage.setProxyImage("https://img.zcool.cn/community/01a5d45543cd170000019ae94fc087.jpg-600@1280w_1l_2o_100sh.jpg-600");

3. 虚拟代理合并 Http 请求

使用场景:点击复选框向服务器发起请求同步文件,每次点击复选框便发起一次请求,造成巨大网络开销,此时我们优化的方式为,将想同步的文件缓存下来,在 3 秒后通过一次请求发送到服务器。

    1 2 3 4 5 6 7 8