1
使用者无权访问目标对象,通过代理做授权和控制

代理模式是一种非常有意义的模式。在生活中也能找到代理模式的情景,比如,明星都有经纪人作为代理,如果想请明星来办一场商业演出,只能联系他的经纪人,经纪人会把商业演出的细节和报酬都谈好之后,再将合同交给明星签。

代理实现图片懒加载

在前端开发中,图片懒加载是一项非常实用的技术。为了性能优化,我们常常在图片加载之前用一张图片占位,等图片加载完成之后再将图片填充到src上,这种场景就很容易实用代理模式。

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() {
        myImage.setSrc(img.src)
    }
    return {
        setSrc: function(src) {
            myImage.setSrc('./loading.gif')
            img.src = src
        }
    }
})()

proxyImage.setSrc('https://user-gold-cdn.xitu.io/2016/11/29/805fd2776ae656464329c04f63181266?imageView2/1/w/180/h/180/q/85/format/webp/interlace/1')

通过proxyImage间接访问MyImage。proxyImage控制来客户对MyImage的访问,并且在此过程中加入一些额外的操作,比如在图片加载前,先将src设置为本地的loading图。

缓存代理

缓存代理可以为一些开销较大的运算结果暂时的存储,在下次运算时,如果传递的值一致,则可以直接返回前面存储的结果。

// 创建一个乘积函数
var mult = function() {
    console.log('开始计算乘积')
    var a = 1
    for(var i = 0, l = arguments.length; i<l ; i++) {
        a = a*arguments[i]
    }
    return a
}
// 加入缓存代理函数
var proxyMult = (function(){
    var cache = {}
    return function() {
        var args = Array.prototype.join.call(arguments, ',')
        if (args in cache) {
            return cache[args]
        }
        return cache[args] = mult.apply(this, arguments)
    }
})()

proxyMult(1,2,3,4) //24
proxyMult(1,2,3,4) //24

当第二次调用proxyMult的时候,本体mult并没有直接计算,proxyMult直接返回之前的结果

引入代理的意义

为了说明代理的意义,下面引入一个面向对象的设计原则:单一职责原则

  1. 一个类(对象或者函数)而言,应该只能有一个引起它变化的原因。如果一个对象承担了多项职责,那么引起变化的原因可能就有多个。
  2. 实际上增加懒加载图片只是一个景上添花的行为。纵观整个程序,我们并没有改变myImage的接口,但是通过代理,给接口添加了新的行为,如果某天不需要了,也不用修改本体。

YiHzo
193 声望9 粉丝