代理模式是一種結構型設計模式,它可以為其他對象提供一種代理以控制對這個對象的訪問。
所謂代理,是指具有與被代理對象相同的接口的類,客戶端必須通過代理與被代理的目標類進行交互,而代理一般在交互的過程中(交互前后),進行某些特定的處理。
代理模式中的UML圖如下:
代理模式中的角色:
1.抽象對象角色
聲明了目標類及代理類對象的共同接口,這樣在任何可以使用目標對象的地方都可以使用代理對象。
2.目標對象角色
定義了代理對象所代表的目標對象。
3.代理對象角色
代理對象內部含有目標對象的引用,從而可以在任何時候操作目標對象;代理對象和目標對象具有統一的接口,以便可以再任何時候替代目標對象。代理對象通常在客戶端調用傳遞給目標對象之前或者之后,執行某些操作,而非單純的將調用傳遞給目標對象。
下面給出示例代碼:
首先定義AbstractObject類,在其中定義代理類和目標類共有的接口operation()
1 public abstract class AbstractObject { 2 protected abstract void operation(); 3 }
下面定義目標實現類:
1 public class RealObject extends AbstractObject { 2 @Override 3 protected void operation() { 4 System.out.println("do operation..."); 5 } 6 }
下面是代理類:
1 public class ProxyObject extends AbstractObject { 2 //對目標類的引用 3 private RealObject realObject; 4 5 public ProxyObject(RealObject realObject) { 6 this.realObject = realObject; 7 } 8 9 @Override 10 protected void operation() { 11 System.out.println("do something before real peration..."); 12 if(realObject == null){ 13 realObject = new RealObject(); 14 } 15 realObject.operation(); 16 System.out.println("do something after real operation..."); 17 } 18 }
下面是測試類:
1 public class ProxyTest { 2 public static void main(String[] args) { 3 AbstractObject proxy = new ProxyObject(new RealObject()); 4 proxy.operation(); 5 } 6 }
執行結果如下:
從這個例子可以看出,代理對象將客戶端的調用委派給了目標對象,在調用目標對象之前及之后都可以執行某些特定的操作。
總結:
代理模式的使用場景:
如果已有的方法在使用的時候需要對原有的方法進行改進,此時有兩種辦法:
(1)修改原有的方法來適應。顯然這違反了“對擴展開放,對修改關閉”的原則。
(2)采用一個代理類調用原來的方法,且對產生的結果進行控制。這就是代理模式了。
使用代理模式可以將功能划分的更加清晰,有助於后期的維護。
以上所說的這種代理模式稱為靜態代理。
擴展:
Spring框架是時下很流行的Java開源框架,Spring之所有如此流行,跟它自身的特性是分不開的。Spring本身含有兩大特性,一個是IOC,一個是AOP的支持。
IOC是Inverse Of Control,即控制反轉,也有人把IOC稱作依賴注入。我覺得依賴注入這種說法很好理解,但不完全對。依賴注入是Dependency Injection的縮寫,是實現IOC的一種方法,但不等同於IOC,IOC是一種思想,DI只是一種實現。
AOP是Aspect Oriented Programming的縮寫,即面向切面編程。與面向過程和面向對象的編程方式相比,面向切面編程提供了一種全新的思路,解決了OOP編程過程中的一些痛點。
IOC的實現原理是利用了JAVA的反射技術,那么AOP的實現原理是什么呢?——動態代理技術
目前動態代理技術主要分為Java自己提供的JDK動態代理技術和CGLIB技術。Java自帶的JDK動態代理技術是需要接口的,而CGLIB則是直接修改字節碼。
針對這兩種動態代理技術,筆者在后面會單獨寫一篇文章加以介紹,在此不過多解釋。