Fork me on GitHub

代理模式的应用


虚拟代理实现图片预加载

图片预加载:图片过大或者网络不佳时,图片位置有段时间会是一片空白,常见的用一张loading占位,然后异步加载图片,等图片加载好了再把它填充到img节点里。

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

这里我们通过proxyImage间接地访问MyImage,proxyImage控制了客户对MyImage的访问,因此在此过程中加入一些额外的操作,比如在真正图片加在之前先把img的节点的src设置成一张本地的图片。

虚拟代理合并http请求

假设我有一堆选项(checkbox),每次点击就会往服务器同步文件,手速快的一秒或许可以点中四五个,然而太过平凡的服务器请求开销略大。
因此,我们决定设置一个代理函数,将两秒之内的数据传输收集到一起两秒再发送一次,对于实时性要求不是很高的系统两秒延迟不会有太大副作用但是对服务器的压力就是量级的减少。

var synchronousFile = function(id) {
    console.log('开始同步文件' + id);
};

var proxySynchronousFile = (function() {
    var cache = [], //保存一段时间内需要同步的ID
        timer;
    return function(id) {
        cache.push(id);
        if (timer) { //保证不会覆盖已启动的定时器
            return;
        }
        timer = setTimeout(function() {
            synchronousFile(cache.join(',')); //两秒后向本体发送需要同步的ID集合
            clearTimeout(timer);
            timer = null;
            cache.length = 0;
        }, 2000);
    }
})();

var chechbox = document.getElementByTagName('input');
for(var i = 0, c; c = checkbox[i++];) {
    c.onclick = function() {
        if(this.checked === true) {
            proxySychronousFile(this.id);
        }
    }
}

其他代理模式

  • 缓存代理:为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传过来的参数跟之前的一直可以直接返回前面的存储运算结果

  • 防火墙代理:控制网络资源的访问,保护主题不让“坏人”接近

  • 远程代理:为一个对象在不同的地址空间提供局部代表

  • 保护代理:用于对象应该有不同访问权限的情况

  • 智能引用代理:取代了简单的指针,它在访问对象时执行了一些附加操作,比如计算一个对象被引用的次数

  • 写时服饰代理:通常用于复制一个庞大对象时候的情况。写时复制代理延迟了复制的过程,当对象被真正修改时,才能对它进行复制操作。
    …..

我知道是不会有人点的,但万一有人想不开呢?