240
每个人都有属于自己的一片森林,也许我们从来不曾去过,但它一直在那里,总会在那里。迷失的人迷失了,相逢的人会再相逢!

JS 设计模式六 -- 代理模式

概念

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

当客户不方便直接访问一个对象的时候,需要提供一个替身对象来控制对这个对象的访问。

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

 

实现

代理模式共有三种:保护代理、虚拟代理、缓存代理

保护代理:

用于控制不同权限的对象对目标权限的访问,实现访问访问主题的控制行为。

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

// 代理,对消息进行过滤
function proxySendMsg(msg) {
    // 无消息则直接返回
    if (typeof msg === 'undefined') {
        console.log('No Msg');
        return;
    }
    
    // 有消息则进行过滤
    msg = "收到的msg是:" + msg;

    sendMsg(msg);
}


sendMsg("msg1"); // msg1
proxySendMsg('msg2'); // 收到的msg是:msg2
proxySendMsg(); // No Msg

 

虚拟代理

虚拟代理 用于控制对创建开销很大的本体访问,它会把本体的实例化推迟到有方法被调用的时候,是最常用的一种代理。

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

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("http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif");
            img.src = src;
        }
    }
})();
// 调用方式
ProxyImage.setSrc("https://img.alicdn.com/tps/i4/TB1b_neLXXXXXcoXFXXc8PZ9XXX-130-200.png");

 

使用虚拟代理实现函数防抖

// 函数防抖,频繁操作中不处理,直到操作完成之后(再过 delay 的时间)才一次性处理,执行最后一次操作
function debounce(fn, delay) {
    delay = delay || 200;
    
    var timer = null;

    return function() {
        var arg = arguments;
          
        // 每次操作时,清除上次的定时器
        clearTimeout(timer);
        timer = null;
        
        // 定义新的定时器,一段时间后进行操作
        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;

 

缓存代理

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

 

使用缓存代理计算乘法、加法

// 计算乘法
var mult = function(){
    var a = 1;
    for(var i = 0,ilen = arguments.length; i < ilen; i+=1) {
        a = a*arguments[i];
    }
    return a;
};
// 计算加法
var plus = function(){
    var a = 0;
    for(var i = 0,ilen = arguments.length; i < ilen; i+=1) {
        a += arguments[i];
    }
    return a;
}
// 代理函数
var proxyFunc = function(fn) {
    var cache = {};  // 缓存对象
    return function(){
        var args = Array.prototype.join.call(arguments,',');
        if(args in cache) {
            return cache[args];   // 使用缓存代理
        }
        return cache[args] = fn.apply(this,arguments);
    }
};
var proxyMult = proxyFunc(mult);
console.log(proxyMult(1,2,3,4)); // 24
console.log(proxyMult(1,2,3,4)); // 缓存取 24

var proxyPlus = proxyFunc(plus);
console.log(proxyPlus(1,2,3,4));  // 10
console.log(proxyPlus(1,2,3,4));  // 缓存取 10

 

posted @ 2019-04-22 14:54  _gxing  阅读(707)  评论(0编辑  收藏  举报