每天一個設計模式(8):代理模式


  首先說下,本來寫這個設計模式的系列,打算每天總結一個設計模式的,但是真的是太忙了(尤其是最近),導致現在的情況和本系列名字“每天一個設計模式”極不相符,真是尷尬啊,/(ㄒoㄒ)/~~

  但是,最近在復習Spring的AOP的時候,涉及到了代理模式,所以,還是抽出時間把代理模式總結一下,由於現在時間真的是有限,故本文參考了一些優秀的博主的相關文章,文末給出了參考鏈接。

  正文開始了:

一. 定義

  代理模式為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。對一個對象進行訪問控制的一個原因是為了只有在我們確實需要這個對象時才對它進行創建和初始化。它是給某一個對象提供一個替代者(占位者),使之在client對象和subject對象之間編碼更有效率。

  比如我們在租房子的時候回去找中介,因為你對該地區房屋的信息掌握的不夠全面,希望找一個更熟悉的人去幫你做,此處的代理就是這個意思。再如我們有的時候打官司,我們需要請律師,因為律師在法律方面有專長,可以替我們進行操作,表達我們的想法。

二. UML關系圖

三. 模式的組成

代理模式中有三種角色:

1. 代理角色(Proxy)

  代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當於對真實對象進行封裝。

2.  抽象角色(Subject)

  聲明真實對象和代理對象的共同接口。

  這樣就在任何使用RealSubject的地方都可以使用Proxy。代理角色通過持有真實角色RealSubject的引用,不但可以控制RealSubject的創建或刪除,可以在RealSubject被調用前進行攔截,或在調用后進行某些操作。

3.  真實角色(RealSubject)

  代理角色所代表的真實對象,是我們最終要引用的對象。

四. 優缺點

優點

  代理模式能夠協調調用者和被調用者,在一定程度上降低了系統的耦合度。使用代理模式,可以將功能划分的更加清晰,有助於后期維護。

缺點

  由於在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢。
  實現代理模式需要額外的工作,有些代理模式的實現非常復雜。

五. 實現代碼

1 //抽象對象角色
2 public abstract class AbstractObject {
3     //操作
4     public abstract void operation();
5 }
1 //目標對象角色
2 public class RealObject extends AbstractObject {
3     @Override
4     public void operation() {
5         //一些操作
6         System.out.println("一些操作");
7     }
8 }
 1 //代理對象角色
 2 public class ProxyObject extends AbstractObject{
 3     RealObject realObject = new RealObject();
 4     @Override
 5     public void operation() {
 6         //調用目標對象之前可以做相關操作
 7         System.out.println("before");        
 8         realObject.operation();        
 9         //調用目標對象之后可以做相關操作
10         System.out.println("after");
11     }
12 }
 1 //客戶端
 2 public class Client {
 3 
 4     public static void main(String[] args) {
 5         // TODO Auto-generated method stub
 6         AbstractObject obj = new ProxyObject();
 7         obj.operation();
 8     }
 9 
10 }

六. 應用場景

  當我們需要使用的對象很復雜或者需要很長時間去構造,這時就可以使用代理模式(Proxy)。例如:如果構建一個對象很耗費時間和計算機資源,代理模式(Proxy)允許我們控制這種情況,直到我們需要使用實際的對象。一個代理(Proxy)通常包含和將要使用的對象同樣的方法,一旦開始使用這個對象,這些方法將通過代理(Proxy)傳遞給實際的對象。 一些可以使用代理模式(Proxy)的情況:

  • 一個對象,比如一幅很大的圖像,需要載入的時間很長。    
  • 一個需要很長時間才可以完成的計算結果,並且需要在它計算過程中顯示中間結果
  • 一個存在於遠程計算機上的對象,需要通過網絡載入這個遠程對象則需要很長時間,特別是在網絡傳輸高峰期。
  • 一個對象只有有限的訪問權限,代理模式(Proxy)可以驗證用戶的權限

  代理模式(Proxy)也可以被用來區別一個對象實例的請求和實際的訪問,例如:在程序初始化過程中可能建立多個對象,但並不都是馬上使用,代理模式(Proxy)可以載入需要的真正的對象。這是一個需要載入和顯示一幅很大的圖像的程序,當程序啟動時,就必須確定要顯示的圖像,但是實際的圖像只能在完全載入后才可以顯示!這時我們就可以使用代理模式(Proxy)。

  使用代理模式來將由一系列無關邏輯組合在一起的代碼進行解耦合,比如業務代碼中的日志代碼就可以在代理中進行。spring的AOP就是典型的動態代理應用。

七. 動態代理

  動態代理之所以被稱為動態,是因為運行時才將它的類創建出來。代碼開始執行時,還沒有proxy類,它是根據需要從你傳入的接口集創建的。Proxy本身是利用靜態的Proxy.newProxyInstance()方法在運行時動態地創建的。代理類有一個靜態方法isProxyClass(),此方法的返回值如果為true,表示這是 一個動態代理類。

  動態代理的UML關系圖如下:

  可以把InvocationHandler想成是代理收到方法調用后,請求做實際工作的對象。其中只有一個invoke()方法,不管代理被調用的是何種方法,處理器被調用的一定是invoke()方法。

八. 代理模式的應用形式

  1. 遠程代理(Remote Proxy) -可以隱藏一個對象存在於不同地址空間的事實。也使得客戶端可以訪問在遠程機器上的對象,遠程機器可能具有更好的計算性能與處理速度,可以快速響應並處理客戶端請求。
  2. 虛擬代理(Virtual Proxy) – 允許內存開銷較大的對象在需要的時候創建。只有我們真正需要這個對象的時候才創建。
  3. 寫入時復制代理(Copy-On-Write Proxy) – 用來控制對象的復制,方法是延遲對象的復制,直到客戶真的需要為止。是虛擬代理的一個變體。
  4. 保護代理(Protection (Access)Proxy) – 為不同的客戶提供不同級別的目標對象訪問權限
  5. 緩存代理(Cache Proxy) – 為開銷大的運算結果提供暫時存儲,它允許多個客戶共享結果,以減少計算或網絡延遲。
  6. 防火牆代理(Firewall Proxy) – 控制網絡資源的訪問,保護主題免於惡意客戶的侵害。
  7. 同步代理(SynchronizationProxy) – 在多線程的情況下為主題提供安全的訪問。
  8. 智能引用代理(Smart ReferenceProxy) - 當一個對象被引用時,提供一些額外的操作,比如將對此對象調用的次數記錄下來等。
  9. 復雜隱藏代理(Complexity HidingProxy) – 用來隱藏一個類的復雜集合的復雜度,並進行訪問控制。有時候也稱為外觀代理(Façade Proxy),這不難理解。復雜隱藏代理和外觀模式是不一樣的,因為代理控制訪問,而外觀模式是不一樣的,因為代理控制訪問,而外觀模式只提供另一組接口。

 

參考:http://blog.csdn.net/jackiehff/article/details/8621517

http://www.cnblogs.com/java-my-life/archive/2012/04/23/2466712.html

http://www.cnblogs.com/mengdd/archive/2013/05/07/3065619.html

http://blog.csdn.net/zhangerqing/article/details/8239539

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM