javascript中的設計模式之代理模式

1、定義ajax

當客戶不方便直接訪問一個對象或者不知足須要的時候,提供一個對象來控制堆這個對象的訪問。後端

2、舉例api

惰性單例模式的實現依靠緩存代理緩存

3、結構閉包

代理模式須要一個本體對象和一個代理對象。在代理模式下,對於本體對象的特定的操做經過代理對象進行。如圖所示async

 

 

   這種模式的關鍵點在於:本體對象和代理對象接口的一致性也就是說若是須要不經過代理進行操做,那麼直接操做本體對象依然能夠。post

4、實現性能

代理模式分爲不少類,其中常常用到的有保護代理、虛擬代理、緩存代理。spa

1.保護代理代理

保護代理的做用是當對本體對象的屬性進行訪問和賦值時,代理對象能夠對其進行攔截。

ES6中,代理是一個已經被實現的知識點,以下:

var obj = {
    _name: "JYY",
    age: 29
};
var objProxy = new Proxy(obj, {
    get: function(target, key){
        if(key === "_name") return undefined;
        return target[key];
    },
    set: function(target, key){
        if(key === "_name") return;
    }
});
objProxy._name; // undefined
objProxy.age; // 29

上面的代碼中obj是本體對象,objProxy是代理對象,這個代理實現了禁止訪問和設置內部私有屬性的功能。在這段代碼中,咱們使用代理對象對本體對象的get和set方法進行了代理,本體對象和代理對象都包含了這個set和get接口(obj對象自己內部實現了get和set),因此若是咱們繞過代理對象直接訪問和賦值本體對象也是能夠的:

var obj = {
    _name: "JYY",
    age: 29
};
console.log(obj._name); //JYY
obj._name = "hah";
console.log(obj._name); // hah

保護代理的重點在於,代理對象保護外界對於本體對象的可訪問和可操做性,也就是說在保護代理中,代理對象是用於禁止外界對本體對象的操做,防止本體對象的屬性被外界進行操做

2.虛擬代理

虛擬代理在我理解,就是用戶認爲已經執行了某個功能,事實上卻時使用代理對象進行佔位,待觸發的時機到來,纔會真正的執行本體對象的操做。也就是虛擬代理把一些開銷很大的對象,延遲到真正須要他的時候才採起建立。所以虛擬代理的使用伴隨的是性能的提高。

典型的虛擬代理的例子就是節流,以下所示:

var resizeProxy = function(fn){
    let timer = null;
    return function(){
        if(!timer){
            timer = setTimeout(function(){
                fn && fn();
                timer = null;
            },1000)
        }
    }
};
var resizeChange = function(){
    console.log(1);
};
window.onresize = resizeProxy(resizeChange);

這段代碼是經典的使用節流控制窗體尺寸大小改變事件觸發的例子,做用就是讓resize事件的觸發不那麼頻繁,自定義的控制觸發的頻率,這對於性能的提高頗有幫助。

在這段代碼裏面,resizeChange就是本體,resizeProxy就是代理,若是不使用代理直接將fn複製給window.onresize依舊是可用的。而使用代理的做用就是首先進行佔位,開發中代理內部的代碼是不可見的(好比提供的是api),利用resizeProxy的不可見性,讓客戶認爲已經調用了功能代碼,可是事實上是咱們並未當即執行代碼,由於咱們做爲開發者知道當即執行會帶來性能的喪失,只有在合適的時機咱們纔會委託代理執行本地代碼,執行真正的業務代碼。

3.緩存代理

緩存代理在單例模式中就已出現,用於建立惰性代理模式,其原理就是在須要時建立對象,並將該對象保存在閉包中,這樣能夠一次建立屢次使用。

固然在惰性單例中使用是緩存代理最簡單的實現方式。在實際開發中,咱們可能會遇到這樣的場景,在tab中每一個tab頁都包含多個圖表,所以在點擊tab的時候就須要獲取這個tab對應的圖表的數據,這些數據都須要從後端請求。好比以某個省的地市經濟統計狀況爲例,咱們須要的頁面以下:

 

可見這樣的狀況下,用戶極可能不斷地點擊tab切換城市,而後和其餘城市進行對比。若是每次點擊都請求數據,帶給用戶的體驗會很是差。這樣的狀況下,咱們就能夠作個全局的緩存,固然你能夠保存在組件的狀態中,除此以外緩存代理也是個很棒的選擇。代碼以下:

// 請求數據
function requestData(regionName){
    return new Promise(function(resolve, reject){
        var rest = ajax({
            type: "post",
            params: {regionName: regionName}
        })
        resolve(rest);
    })

}
// 初始化數據代理方法
var proxyInit = (function(){
    var cache = {};
    return async function(regionName){
        if(cache[regionName]){
            return cache[regionName];
        }else{
            return cache[regionName] = await requestData(regionName);
        }
    }
});
proxyInit("石家莊");

 5、總結

三種類型雖然均爲代理模式,可是各自的目的並不相同,保護代理是爲了阻止外部對內部對象的訪問或者是操做等;虛擬代理是爲了提高性能,延遲本體執行,在合適的時機進行觸發,目的是減小本體的執行次數;緩存代理一樣是爲了提高性能,可是爲了減緩內存的壓力,一樣的屬性,在內存中只保留一份。

 

相關文章
相關標籤/搜索