设计模式——代理模式

293 阅读2分钟

代理模式相当于聘用一个助理,助理为你处理一些琐事,尽可能的减少你的工作量,自己去处理一些核心(自己不得不做)的工作。

  1. 定义

为一个对象提供一个代用品或占位符,以便控制对它的访问

  1. 核心

当客户不方便直接访问一个 对象或者不满足需要的时候,提供一个替身对象 来控制对这个对象的访问,客户实际上访问的是 替身对象。

替身对象对请求做出一些处理之后, 再把请求转交给本体对象

代理和本体的接口具有一致性,本体定义了关键功能,而代理是提供或拒绝对它的访问,或者在访问本体之前做一 些额外的事情

  1. 实现

代理模式主要有三种:保护代理虚拟代理缓存代理

保护代理主要实现了访问主体的限制行为,以过滤字符作为简单的例子

// 主体,发送消息
function sendMsg(msg) {
    console.log(msg);
}

// 代理,对消息进行过滤
function proxySendMsg(msg) {
    // 无消息则直接返回
    if (typeof msg === 'undefined') {
        console.log('deny');
        return;
    }
    
    // 有消息则进行过滤
    msg = ('' + msg).replace(/泥\s*煤/g, '');

    sendMsg(msg);
}


sendMsg('泥煤呀泥 煤呀'); // 泥煤呀泥 煤呀
proxySendMsg('泥煤呀泥 煤'); // 呀
proxySendMsg(); // deny

它的意图很明显,在访问主体之前进行控制,没有消息的时候直接在代理中返回了,拒绝访问主体,这数据保护代理的形式

有消息的时候对敏感字符进行了处理,这属于虚拟代理的模式

虚拟代理在控制对主体的访问时,加入了一些额外的操作

在滚动事件触发的时候,也许不需要频繁触发,我们可以引入函数节流,这是一种虚拟代理的实现

function debounce(fn, delay) {
    delay = delay || 200;
    var timer = null;
    return function() {
        var arg = arguments;
        // 每次操作时,清除上次的定时器
        clearTimeout(timer);
        // 定义新的定时器,一段时间后进行操作
        timer = setTimeout(function() {
            fn.apply(this, arg);
        }, delay);
    }
};
var count = 0;
// 主体
function scrollHandle(e) {
    console.log(e.type, ++count); // scroll
}
// 代理
var proxyScrollHandle = (function() {
    return debounce(scrollHandle, 500);
})();
window.onscroll = proxyScrollHandle;

缓存代理可以为一些开销大的运算结果提供暂时的缓存,提升效率

来个栗子,缓存加法操作

        //  主体
        function add() {
            var arg = [].slice.call(arguments);
            console.log("计算");
            return arg.reduce((a, b) => a + b);
        }
        // 代理
        var proxyAdd = (function () {
            var cache = [];
            return function () {
                var arg = [].slice.call(arguments);
                if(cache[arg]){
                    return cache[arg]
                }else{
                    cache[arg]=add.apply(this,arg);
                    return cache[arg]
                }
            }
        })()

        console.log(
            add(1, 2, 3, 4),
            proxyAdd(10, 20, 30, 40),
            proxyAdd(10, 20, 30, 40),
            proxyAdd(10, 20, 30, 40)
        ); // 10 100 100 100