Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

代理模式 #15

Open
archerU opened this issue Jun 5, 2018 · 0 comments
Open

代理模式 #15

archerU opened this issue Jun 5, 2018 · 0 comments

Comments

@archerU
Copy link
Owner

archerU commented Jun 5, 2018

代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理之后,再把请求转交给本体对象。

虚拟代理

图片预加载

图片预加载是一种常用的技术,如果直接给某个img标签节点设置src属性,由于图片过大或者网络不佳,图片的位置往往有段时间会是一片空白。常见的做法是先用一张 loading 图片占位,然后用异步的方式加载图片,等图片加载好了再把它填充到img节点里,这种场景就很适合使用虚拟代理。

// 伪代码
const myImage = (function(){
    const imgNode = document.createElement("img");
    document.body.appendChild(imgNode);
    return {
        setSrc: function(src) {
            imgNode.src = src;
        }
    }
})();

const proxyImage = (function(){
    const img = new Image;
    img.onload = function() {
        myImage.setSrc(this.src);
    }
    return {
        setSrc: function(src) {
            myImage.setSrc('file:// c/.../gif');
            img.src = src;
        }
    }
})();

proxyImage.setSrc('http://.../.jpg');

合并HTTP请求

// 伪代码
const synchronousFile = function(id) {
      console.log("开始同步文件,id 为" + id);
};

const proxySynchronousFile = (function(){
    const cache = [], // 保存 
    timer; // 定时器
    
    return function(id) {
        cache.push(id);
        if (timer) { // 保证不会覆盖已经启动的定时器
            return;
        }
        timer = setTimeout(function() {
            synchronousFile(cache.join(',')); //2 秒后向
            clearTime(timer); // 清空定时器
            timer = null;
            cache.length = 0; // 清空 ID 集合
        },2000);
    }
})();
const checkbox = document.getElementsByTagName('input');

for (let i=0,c;c = checkbox[i++]) {
    c.onClick = function() {
        if (this.checked) {
            proxySynchronousFile(this.id);
        }
    }
}

缓存代理

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

// 计算乘积
const mult = function() {
    console.log("开始计算面积");
    let a = 1;
    for (let i=0,length=arguments.length;i<length;i++){
        a = a * arguments[i];
    }
    return a;
};

const proxyMult = (function(){
    const cache = {};
    return function() {
        const 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(1,2,3,4)的时候,本体 mult 函数并没有计算,proxyMult 直接返回了之前缓存好的计算结果。
缓存代理还可以用于 ajax 异步请求数据。

保护代理

保护代理用于控制不同权限的对象对目标对象的访问。

防火墙代理

控制网络资源的访问,保护主题不让“坏人”接近。

远程代理

为一个对象在不同的地址空间提供局部代表,在 Java 中,远程代理可以是一个虚拟机中的对象。

智能引用代理

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

写时复制代理

通常用于复制一个庞大对象的情况。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant