JavaScript代理模式应用及实现

代理模式

定义

代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

举个栗子:假如我现在想买一辆车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。

在这里插入图片描述

为什么要使用代理模式

(1)起中介隔离作用:当客户类不想或者不能直接引用一个委托对象(目标对象),而代理类对象可以在客户类和委托对象之间起到一个中介的作用,其特征是代理类和委托类实现相同的接口。

(2)符合开闭原则,增加功能:我们可以通过给代理类增加额外功能来扩展委托类的功能,这样我们只需要修改代理类而不需要修改委托类,符合代码设计的开闭原则。

代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。

真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

代理模式的类型

(1) 远程代理:为位于两个不同地址空间对象的访问提供了一种实现机制。

可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高系统的整体运行效率。

(2) 虚拟代理:把一些开销很大的对象,延迟到真正需要它的时候才去创建执行。

通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销。

(3) 缓存代理:可以作为一些开销大的运算结果提供暂时的存储,下次运算时,如果传递进来堵塞参数跟之前一致,则可以直接返回前面存储的运算结果。优化系统性能,缩短执行时间。

(4) 保护代理:可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限(保护代理可以帮助过滤一些不合理的请求)。

代理模式适用场景

代理模式的类型较多,不同类型的代理模式有不同的优缺点,它们应用于不同的场合:

(1) 当客户端对象需要访问远程主机中的对象时可以使用远程代理

(2)当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。

(3)当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓存代理。通过使用缓存代理,系统无须在客户端每一次访问时都重新执行操作,只需直接从临时缓冲区获取操作结果即可。

(4) 当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理

(5) 当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。

代理模式也有一定的优缺点:

优点:

(1)代理模式能够将代理对象与被调用的对象分离,降低了系统的耦合度。

(2)代理模式在客户端和目标对象之间起到一个中介作用,这样,可以起到保护目标对象的作用。

(3)代理对象也可以对目标对象调用之前进行其他的操作。

缺点:

增加了系统的复杂度

小例子

先来看一个简单的例子。

1、文子想送给喜欢的男孩子一个节日礼物,但是不好意思,于是就找男孩的好朋友,让男孩的朋友把礼物转交到男孩手里。

var Gift=function(name){
    this.name=name
    this.getName=function(){
        return this.name
    }
}
var wenzi={
    sendGift:function(dl){
        var gift=new Gift('手办盲盒')
        dl.receiveGift(gift.getName())
    }
}
var pengyou={   //朋友代理
    receiveGift:function(gift){
        nanhai.receiveGift(gift)
    }
}
var nanhai={
    receiveGift:function(gift){
        console.log('谢谢你的礼物'+gift)
    }
}
wenzi.sendGift(pengyou)

在这里呢,男孩的朋友就相当于是一个代理。

2、虚拟代理的一个应用在于实现图片预加载

不使用虚拟代理时加载图片:

 var myImage = (function () {
    var imgNode = document.createElement('img');
    document.body.appendChild(imgNode);
    return {
      setSrc: function (src) {
        imgNode.src = src;
      }
    }
  })();
  myImage.setSrc('https://segmentfault.com/img/bVbmvnB?w=573&h=158');

如果图片非常大的话,用户加载图片时会出现很长时间是空白,可以在加载图片完成之前显示一个loading的图片。

使用虚拟代理实现图片预加载:

var myImage = (function () {
    var imgNode = document.createElement('img');
    document.body.appendChild(imgNode);
    return {
        setSrc: function (src) {
            imgNode.src = src
        }
    }
})();    //调用插入图片节点函数

var proxyImage = (function() {  //虚拟代理
    var img = new Image()
    img.onload = function() {
       // setTimeout(()=>{
        	myImage.setSrc(img.src)
        //},2000)
    }
    return {
        setSrc: function (src) {
            img.src = src
            myImage.setSrc('https://content.igola.com/static/WEB/images/other/loading-searching.gif')  //预加载图片
        }
    }
})()
proxyImage.setSrc('9.png.gif');   //要显示的图片
//如果图片非常大,先显示预加载图,再显示图片
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值