設計模式之代理模式
1、什麼是代理模式:
代理模式(Proxy)爲另一個對象提供一個替身或佔位符以控制對這個對象的訪問,簡而言之就是用一個對象來代表另一個對象。
就是一個接口由兩個類來實現,一個是真實角色,一個是代理角色。
代理可以提供延遲實例化(lazy instantiation),控制訪問, 等等。
2、代理模式中的角色:
抽象角色:聲明的共同接口或者是抽象類。
代理角色:代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象能代替真實對象。同時,代理對象可以附加其他的操作,相當於對真實對象進行封裝。
真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。
3、什麼時候使用代理模式:
當我們需要使用的對象很複雜或者需要很長時間去構造,這時就可以使用代理模式(Proxy)。
一個對象,比如一幅很大的圖像,需要載入的時間很長。
一個需要很長時間纔可以完成的計算結果,並且需要在它計算過程中顯示中間結果
一個存在於遠程計算機上的對象,需要通過網絡載入這個遠程對象則需要很長時間,特別是在網絡傳輸高峯期。
一個對象只有有限的訪問權限,代理模式(Proxy)可以驗證用戶的權限
4、代理模式的分類:
1、靜態代理:
主要實現思路:
1) 兩個類都實現一個公共的接口。真實角色實現接口,重寫方法;
2) 代理類與真實角色的區別是:在代理類中創建一個私有的真實角色的對象,並寫有參構造。也就是說:
首先代理類持有真實角色的一個引用。
然後在重寫接口的方法的時候,用真實角色的引用調用真實角色的實現方法。
2、動態代理:
主要作用:藉助於JVM的支持,可以在運行時動態生成代理類(“代理角色”),就可以解決代理模式中代碼膨脹的問題,使用了動態代理後,“代理角色”將不用手動生成,而由JVM在運行時,通過指定類加載器、接口數組、調用處理程序這3個參數來動態生成。
從JDK1.3開始,java中引入了動態代理機制。
相關的接口或類有如下兩個:InvocationHandler和Proxy,都位於java.lang.reflect包下。
InvocationHandler接口只定義了一個抽象方法:
Object invoke(Object proxy, Method method, Object[] args)
Proxy類中主要的2個靜態方法:
Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) 返回一個動態創建的代理類(Class)
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)返回一個改代理類的一個實例(Object)
參數:
Loader:代理類的classloader;
Interface:代理類實現的接口列表:
H:調用處理器,就是從下面說的中介類;
注意:上述方法進行創建對象後,當執行該代理對象調用方法的時候,jvm會動態指派“調用處理器”,向外層invoke傳遞參數,並調用method.invoke()執行;
中介類:(調用處理器)
在真實角色和代理角色之間有一箇中介類,需要
① 實現invocationhandler接口,這個中介類叫做“調用處理器”,攔截對代理類方法的調用。該接口只有一個invoke()方法,裏面有三個參數,
分別是:
proxy參數是代理類對象,
method是具體調用的代理類的那個方法,
args是這個方法的參數。
② 私有化真實角色----有參構造
真實角色、中介類關係:
真實角色 |
真實類 |
中介類 |
代理類 |
中介類、代理角色關係:
中介類 |
真實類 |
代理角色 |
代理類 |
總結:動態代理就是兩個靜態代理關係組成。