代理模式之強制代理模式以及動態代理原理

 

1:強制代理模式

         普通代理模式和強制代理模式是代理模式的其中倆個部分。對於這倆個代理模式,我們採用一個類似事情解釋下:

在網絡上的代理服務器分透明代理和普通代理;對於透明代理來說,字如其意,就是這個代理服務器對用戶來說是透明的,用戶根本不知道這個服務器的存在。而普通代理則是用戶需要自己手動去設置代理服務器的ip,很顯然,對於這點上,用戶必須知道代理服務器的存在。現在對號入座:代理模式中的強制代理類似網絡上的代理服務器的透明代理,代理模式中的普通代理模式就類似網絡上的代理服務器的普通代理。

普通代理模式比較常見,在這裏就不作多說了,那麼在這裏就重點來看看強制代理模式。

 

        強制代理模式在設計模式中比較怪怪的,很另類。一般的思維都是通過代理模式找到真實的角色,但是強制代理模式反其道而行之,必須強制通過真實角色去查找到到模式,否則不能訪問。換句話說就是有真實角色去管理代理角色。總而言之:就是通過new或者其他方式創建一個真實角色的對象,最後卻是會有真實角色返回他自己的代理角色。類似日常生活中:哥們咱想通過給點錢給某某局長,讓他出面給咱們半個事情,結果他給我們一張他祕書的名片(理由很簡單,這種事情當老大的不會出面),讓他們本想通過局長要做的事情,直接通過祕書去做。其實:祕書能做這些,也就是此局長的權勢;說白了祕書就是該局長的替身,代理。上圖:

 

在接口上設置一個getProxy()方法,真實角色就能可以指定一個自己的代理。除了代理,誰也不能訪問。很顯然,當官的人都是會讓指定的親信做事,其他人信不過,當然不能勝任此事。上代碼:局長抑或祕書至少都是官員

 

 

 

 

真實角色和代理角色都應該實現上面的基類。

 

真實角色,增加一個私有方法,檢查是否爲自己的代理,如果是自己的代理,才能執行自己的方法。接下來看看代替實現:

 

 

 

 

 下面將演示3中場景:

 

運行結果:

 

場景1:

please user pointed proxy receiveMoney
please user pointed proxy sendMoney

 

場景2:

please user pointed proxy receiveMoney
please user pointed proxy sendMoney

 

場景3:

張局長 are starting to receiveMoney
張局長 are starting to sendMoney

 

        所以從上面的實例中可以得出:強制代理的概念就是必須從真實角色中查找返回其代理角色,不允許直接通過調用真實角色的方法,因爲在每次調用真實角色從基類繼承的方法時候,該方法都會先去判斷是否爲代理調用。高層模塊只需訪問真實角色的getProxy(),就可以完成訪問真實角色的所有方法,它根本就不需要產生一個代理處理,代理的管理已經由真實角色自己完成。強制代理模式使得高層模塊與真實角色的業務場景耦合度極地;真實角色的修改,在高層模塊中完全不用修改。倆者只通過真實角色提供的一個getProxy()接口來交互。在整個實現過程,採用回調思想,在真實角色中調用代理對象的方法,代理對象通過回調來調用真實角色的方法。

 

2:動態代理模式

       先解釋下何爲動態代理模式,所謂動態代理模式就是在實現階段毋須關心代理誰,只有在運行階段才指定代理哪一個對象。通俗點講就是:自己動手寫代理類的方式就是靜態代理模式。採用動態代理模式比較爲大家所熟知的比如AOP(切面編程),其核心機制就是採用動態代理機制。我們繼續使用上面的官員行賄和受賄的例子來解析動態代理模式原理:上圖

 

 

 

 

 

在類圖中增加一個InvocationHandler接口;其中InvocationHandler是JDK提供的動態代理接口,對被代理的類(即是真實角色的對象,譬如上例中的局長角色)的方法進行代理。看代碼:

其中invoke方法是InvocationHandler派生類必須實現的方法,它完成對真實角色(祕書調用局長的方法)的方法的調用。動態代理就是根據被代理的真實角色所屬的接口生成所有方法,換而言之:代理對象已經實現接口下(IOfficer)的所有方法。類似靜態代理模式:public class OfficerProxy implements IOfficer 也要實現該接口下所有方法。

 

 

 

運行結果:

張局長 are starting to receiveMoney
張局長 are starting to sendMoney

 

粗看很不解,IOfficer proxy是生成的代理類,但是沒有看到代理類實現接口的方法。(IOfficer) Proxy.newProxyInstance來生成代理對象,裏面到底是如何處理的,我們進去看看Proxy.newProxyInstance這個方法:

 

 

可見關鍵之處在於Class cl = getProxyClass(loader, interfaces);Proxy利用類裝載器和代理類的接口來生成一個實現了接口各個方法的代理類的class對象。我們分析下代碼getProxyClass(loader, interfaces)代碼

 

 

所以:Proxy.newProxyInstance內部機制爲:

 

1:實現接口
2:裝載字節流文件到虛擬機
3:實例化,並返回對象

 

類推:代理對象調用方法:Proxy.sendMoney(),他的實現應該類似如何:

通過InvocationHandler的invoke方法類來調用真實角色對應方法

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章