JS 設計模式六 -- 代理模式

概念

爲一個對象提供一個代用品或佔位符,以便控制對它的訪問。緩存

當客戶不方便直接訪問一個對象的時候,須要提供一個替身對象來控制對這個對象的訪問。app

替身對象對請求作出一些處理以後, 再把請求轉交給本體對象。函數

 

實現

代理模式共有三種:保護代理、虛擬代理、緩存代理this

保護代理:spa

用於控制不一樣權限的對象對目標權限的訪問,實現訪問訪問主題的控制行爲。prototype

// 主體,發送消息
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

 

虛擬代理代理

虛擬代理 用於控制對建立開銷很大的本體訪問,它會把本體的實例化推遲到有方法被調用的時候,是最經常使用的一種代理。code

使用虛擬代理來實現圖片預加載cdn

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
相關文章
相關標籤/搜索