設計模式學習筆記之代理模式


前言

這是本人的設計模式學習筆記,把本身學習過程當中的一些總結和認識記錄下來,與諸君共勉。本日爲你們帶來代理模式。ajax

基本概念

代理的任務是對本體的訪問進行控制,並暴露出與本體徹底相同的接口,將全部對它進行的方法調用傳遞給本體。注意代理既不像裝飾者同樣添加行爲,也不像外觀模式同樣簡化接口,記住:proxy‘s interface = origin’s interface。下面咱們給出代理模式的結構示意圖。設計模式

代理模式結構示意圖

具體類別

遠程代理

遠程代理用於訪問位於另外一個環境中的對象,另外一種環境的意義有着普遍的語義,例如在Java中意味着另外一個JVM中得對象。實現遠程代理須要有客戶端助手也就是代理對象來接受客戶的請求並傳達給服務端,也要有服務端助手來解析請求。遠程對象通常長期存在,下面也給出示意圖。遠程代理也能夠被用來訪問其餘語言中的對象。緩存

遠程代理示意圖

最後,介紹一些術語:安全

  • stub:客戶端助手
  • skeleton:服務端助手

虛擬代理

虛擬代理用於控制對那種建立開銷很大的本體的訪問,將本體的實例化推遲到有方法被調用的時候,有時還會提供關於實例化狀態的反饋。下面給出一張示意圖:服務器

虛擬代理示意圖

jsproxy.prototype._init=function(){
    if(this.entity===null){
        this.entity= new Entity(this.data);
    }
};

保護代理

保護代理一般根據客戶身份控制對特定方法的訪問。多線程

保護代理示意圖

其餘代理

這裏咱們列出一些在上面沒有提到的代理:app

  • 防火牆代理
  • 智能引用代理:主題被引用時,進行額外的計算
  • 緩存代理:爲開銷大的運算結果提供暫時存儲,容許多用戶共享結果以減小實際計算
  • 同步代理:多線程狀況下位主題提供安全的訪問
  • 複雜隱藏代理:用來隱藏一個類的複雜集合的複雜度,並進行訪問控制
  • 寫入時複製代理:延遲對象的複製直到客戶真的須要爲止

代理 vs 裝飾者

  • 裝飾者會擴充或修改原對象的功能,代理僅僅控制它的訪問,最多添加一些控制代碼而不會修改調用方法
  • 裝飾者模式中被包裝對象的實例化過程徹底獨立,代理模式中本體的實例化是代理實例化的一部分
  • 代理不能像裝飾者那樣互相包裝,一次使用一個

應用

先舉一個例子,ajax機制中,你想拉取遠程資源並進行一些操做,你能夠在本地建立代理對象來暴露這些操做接口,而後就像操做本地對象同樣完成操做,實際的xhr對象和遠程請求等均可以隱藏在代理內部,具體能夠參考jQuery的ajax服務。固然每每這種例子不會那麼純粹,它們或多或少帶有裝飾器、外觀模式的種種特色,但它們確實實現了代理的目的,不是嗎?異步

再好比搜索框,它們要查詢服務器並拉取數據,但你並不是每次訪問該頁面都使用搜索框啊,使用虛擬代理就能夠在用戶真的搜索時再請求,固然你會說直接用事件不就得了。可是異步加載的次數和類別夠複雜,你可能會但願僅僅對view暴露接口。虛擬代理總會派上用場。函數

實現

以虛擬代理爲例學習

jsvar Proxy=function(){
    this.args=arguments;
    this.initialized=false;
    this.subject={};//構建的本體
    this.class={...};//本體的構造函數
    ...
    var self=this;
    for(var key in this.class.prototype){
        if(typeof this.class.prototype[key] !== "function") continue;
        (function(methodName){
            self[methodName]=function(){
                if(!self.initialized) return;
                return self.subject[methodName].apply(self.subject,arguments);
            };
        })(key);
    }
};


Proxy.prototype._init=function(){...};
Proxy.prototype._checkInitialization=function(){...};//阻止在初始化以前方法被調用
Proxy.prototype._isInitialized=function(){...};

利弊

  • 遠程代理減小了爲訪問遠程資源而編寫的代碼數量,並提供單一接口,提升模塊性
  • 虛擬代理減小實例化開銷
  • 掩蓋了實例化的邏輯,增長了項目的複雜性,增長類的數目
相關文章
相關標籤/搜索