設計模式--Proxy

轉自:http://blog.csdn.net/dan_xp/article/details/1820852java

最近一直在看java的設計模式 ,感受印象最深入的就是"面向接口編程",在java中,儘可能多定義接口,由於設計的最重要的目的就是應對各 種變化,而接口自己就是一種變化着的Class的直接反映,經過實現特定接口的各類具體類,達到應對變化的目的,下面以Proxy模式爲例:編程

Proxy的模式最主要的目的,原有的類對象因爲某種緣由不能訪問,須要經過一個新的類來間接地去實現,這個新的類就稱爲代理類,舉個例子說明,老王買/賣魚的例子
public   class  SellFisher  {
    
public int sellFish() {
        System.out.println(
"my fish is delicious!!");
        
return 10;
    }

}
這是一個具體的賣魚類,表示魚10元/斤,若是這個類被用到系統中的時候,系統應對變化的靈活性就會大打折扣,請看以下:
public   class  SellFishSystem  {
    
private SellFisher sellfish;
                     
//...
    public void sellFish() {
        sellfish.sellFish();
    }

}
若是之後魚的價格變化,或者具體的賣魚方法發生變化,就必須修改已經有的SellFisher的sellFish()的代碼,這個狀況
使得系統的可擴展性下降,咱們確定會想到解決方案了,定義一個接口,請看代碼:
interface  SellFisher  {
    
int sellFish();
}

public   class  SellFishSystem  {
    
private SellFisher sellfish;
    
public void sellFish() {
        sellfish.sellFish();
    }

}
咱們所作的變化,只是把SellFisher從Class提高到Interface,這個時候好處天然很明顯了,這個SellFisher自己就表明
了一種不肯定,變化.你們在作開發的時候,閱讀源代碼的時候,確定遇到過這種狀況,老是跟蹤類的對象看代碼實現,若是發現了接口變量,就會比較 鬱悶,得了解它的具體實現類是什麼,這個具體實現類的變化一般就能夠應對需求的變化,系以及系統擴展.請看上例子,若是魚的價格變化,或者具體的賣魚方法 發生變化,咱們只須要新增長SellFisher的實現,
而沒必要修改已有的代碼,對此個人理解是對系統來講, 新增長一個類的代碼風險要大大低於對已有類的代碼的修改.我以爲這個也是設計模式的立足點吧(若是你喜歡修改已有代碼,那麼設計模式就沒有多大意義了)
言歸正傳,有了上面的知識準備,咱們接上面的例子來解釋Proxy的模式就簡單多了,好比如今魚的價格變化,賣魚的提示也發生變化了,咱們須要一個新的Proxy類來實現
interface  SellFisher {
    
int  sellFish();
}

public   class  ConcreteSellFisher  implements  SellFisher {

    
public   int  sellFish() {
         System.out.println(
" my fish is delicious!! " );
         
return   10 ;
    }

}

public   class  ProxySellFisher  implements  SellFisher {

    
private  SellFisher sell;
    
public  ProxySellFisher(SellFisher sell) {
        
this .sell  =  sell;
    }
    
public   int  sellFish() {
        System.out.println(
" the fish price higher " );
        
return  sell.sellFish() + 10 ;
    }

}
看上面,這個是Proxy模式的代碼例子實現,咱們如今在SellFishSystem 使用ProxySellFisher來賣魚了,由ProxySellFisher再調用原來的ConcreteSellFisher類.具體的一些特徵總結爲:
1.有個代理類Proxy(和原來的實現類繼承同一接口),該類裏引用了原來的具體功能實現類(這裏是ConcreteSellFisher)
2.重寫實現方法,加一些新的變化的元素(好比魚的價格上漲)
JDK裏的Proxy類也實現了這個模式,只不過它叫動態代理,由於它的代理類變成了InvocationHandler了,執行的方法
是invoke了,從而變得更加靈活了,請看代碼
public   class  ProxySellFisher  implements  InvocationHandler {

    
private  SellFisher sell;
    
public  ProxySellFisher(SellFisher sell) {
        
this .sell  =  sell;
    }
    
public  Object invoke(Object obj, Method method, Object[] args)  throws  Throwable {
        System.out.println(
" the fish price higher " );
        
return  (Integer)method.invoke(sell, args) + 10 ;
    }

}


public   class  ClientTest {
    
public   static   void  main(String args[]) {
        SellFisher s 
=   new  ConcreteSellFisher();
        InvocationHandler p 
=   new  ProxySellFisher(s);
        Object obj 
=  Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(), p);
        ((SellFisher)obj).sellFish();
    }
}
請注意, invoke(Object obj,Method method,Object[] args),這裏的第一個參數obj其實能夠看做沒有用處的,不知道jdk爲何要把它也看成一個參數放這裏,methd.invoke()方法,須要把 原來的具體實現類做爲參數傳遞進去,method.invoke(obj,args)至關於obj.method(args)
總結,從設計模式的角度講,你們之後編程中,儘可能要面向接口,更通俗一點就是, 一個類中使用的別的對象成員變量,最好定義成接口的變量而不是實際實現類的變量
相關文章
相關標籤/搜索