JAVA設計模式-Proxy

代理意思就是說有人幫你做一件事情。舉個例子,現在有一份文件想要領導簽字,但是領導不是隨便就能見的,那麼,就只得先去找領導的祕書,告訴祕書想要找領導簽字,然後祕書會代替你去找領導簽字,然後將簽好字的文件還給你。這麼做有兩個原因,第一個,領導不是隨便就能調用的,在這個例子裏面,領導的簽字功能只有祕書可以調用,當客戶端調用領導簽字這個功能的時候,祕書會把這個調用截獲了,再通過自己去調用領導簽字;第二個,有些字可以籤,有些字簽了是要出問題的,那麼什麼可以籤什麼不可以籤,祕書會進行判斷,祕書會把能籤的給領導,不能籤的直接返回給客戶並告訴他籤不了。講完了上面的例子,回到JAVA的設計上來,使用代理的兩個原因,一,是有些類不能被直接調用,例如它在另一臺機器上,調用的話需要處理網絡,編碼解碼等繁雜的但是跟業務邏輯無關的操作,如果客戶端不用代理直接調用就會寫很多跟業務邏輯無關的代碼,這個和JAVA設計中的功能單一性原則相違背,因爲一旦這個類的位置換了,那麼客戶端就得改,那麼就有可能會影響到業務邏輯,所以這麼做是不行的;第二,有可能這個類某些用戶可以訪問,某些用戶沒權限訪問,那麼如果不使用代理,那麼這個被調用的類不僅要實現自己的功能,還要自己來實現權限判斷的功能,這明顯違背了降低耦合性的原則,於是,就有了代理。

 

    JAVA裏面,代理分爲了兩種,一種是靜態的,沒有用到JDK提供的用於代理模式的類,另一種是動態代理,它用到了JDK裏的一些類。

   

    先來看看靜態的,靜態的很容易理解:

 

   

  1. abstract class Subject {           
  2.     abstract   public   void  request();     
  3. }     
  4.   
  5. // 真實角色:實現了Subject的request()方法。      
  6. class RealSubject extends Subject {     
  7.     public  RealSubject() {      
  8.     }     
  9.     public   void  request() {     
  10.         System.out.println( " From real subject. " );     
  11.     }     
  12. }       
  13.   
  14. // 代理角色:      
  15. class ProxySubject extends Subject {     
  16.     private  RealSubject realSubject;  // 以真實角色作爲代理角色的屬性       
  17.     public  ProxySubject() {     
  18.     }       
  19.     public   void  request() {  // 該方法封裝了真實對象的request方法       
  20.         preRequest();      
  21.         if ( realSubject  ==   null  ) {     
  22.             realSubject  =   new  RealSubject();     
  23.         }     
  24.         realSubject.request();  // 此處執行真實對象的request方法       
  25.         postRequest();      
  26.     }     
  27.     private   void  preRequest() {      
  28.         // something you want to do before requesting       
  29.     }     
  30.     private   void  postRequest() {      
  31.         // something you want to do after requesting       
  32.     }     
  33. }     
  34.   
  35. public class Test{  
  36.     public static void main(String args[]){  
  37.         // 客戶端調用:      
  38.         Subject sub = new  ProxySubject();     
  39.         sub.request();    
  40.     }  
  41. }  

 

    上面這段代碼中,代理類繼承了被代理的類,然後去重載了他的方法,在調用的時候,直接new一個代理類的對象作爲被代理類的對象,這樣就達到了代理的目的。

 

    另外一個是動態代理,來看一段代碼:

 

   

  1. import java.lang.reflect.Constructor;  
  2. import java.lang.reflect.Method;   
  3. import java.lang.reflect.InvocationHandler;     
  4. import java.lang.reflect.Proxy;     
  5.   
  6. interface Subject{   
  7.     public void request();   
  8. }   
  9.   
  10. //具體角色RealSubject:實現了Subject接口的request()方法。    
  11. class RealSubject implements Subject{   
  12.     public RealSubject(){   
  13.   
  14.     }   
  15.     public void request(){   
  16.         System.out.println("From real subject.");   
  17.     }   
  18. }   
  19.   
  20. //代理角色:    
  21. class DynamicSubject implements InvocationHandler{   
  22.     private Object sub;   
  23.     public DynamicSubject(Object sub){              
  24.         this.sub = sub;   
  25.     }   
  26.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
  27.         System.out.println("before calling " + method);   
  28.         method.invoke(sub,args);   
  29.         System.out.println("after calling " + method);   
  30.         return null;   
  31.     }   
  32. }  
  33.   
  34.   
  35. public class Test{      
  36.     @SuppressWarnings("rawtypes")  
  37.     static public void main(String[] args) throws Throwable{     
  38.         RealSubject rs = new RealSubject(); //在這裏指定被代理類      
  39.         InvocationHandler ds = new DynamicSubject(rs); //初始化代理類      
  40.         Class cls = rs.getClass();     
  41.         //以下是分解步驟      
  42.         Class<?> c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces());    
  43.         Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class});    
  44.         Subject subject1 =(Subject) ct.newInstance(new Object[]{ds});    
  45.         subject1.request();   
  46.   
  47.         //以下是一次性生成   
  48.         Subject subject2 = (Subject) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),ds);     
  49.         subject2.request();     
  50.     }    
  51. }  

 

    上面的代碼沒有多少需要解釋的,照着用就行了,但是我還是想說一句,subject1.request()和subject2.request()這兩句話,雖然看似簡單的調用(因爲subject1和subject2都是Subject的對象),實際上,這兩個調用已經被DynamicSubject截獲了,這裏截獲這個詞很能表達代理的意思,理解了截獲這個詞,就能理解Proxy模式了。

 

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