爲什麼要使用代理模式

轉載至:http://www.cnblogs.com/silverLee/archive/2010/02/05/1664577.html

代理這個詞大家肯定已經非常熟悉,因爲現實中接觸的很多,其實現實中的東西恰恰可以非常形象和直觀地反映出模式的抽象過程以及本質。現在房子不是吵得熱火朝天嗎?我們就以房子爲例,來撥開代理的面紗。

假設你有一套房子要賣,一種方法是你直接去網上發佈出售信息,然後直接帶要買房子的人來看房子、過戶等一直到房子賣出去,但是可能你很忙,你沒有時間去處理這些事情,所以你可以去找中介,讓中介幫你處理這些瑣碎事情,中介實際上就是你的代理。本來是你要做的事情,現在中介幫助你一一處理,對於買方來說跟你直接交易跟同中介直接交易沒有任何差異,買方甚至可能覺察不到你的存在,這實際上就是代理的一個最大好處。

接下來我們再深入考慮一下爲什麼你不直接買房子而需要中介?其實一個問題恰恰解答了什麼時候該用代理模式的問題。

原因一:你可能在外地上班,買房子的人沒法找到你直接交易。

對應到我們程序設計的時候就是:客戶端無法直接操作實際對象。那麼爲什麼無法直接操作?一種情況是你需要調用的對象在另外一臺機器上,你需要跨越網絡才能訪問,如果讓你直接coding去調用,你需要處理網絡連接、處理打包、解包等等非常複雜的步驟,所以爲了簡化客戶端的處理,我們使用代理模式,在客戶端建立一個遠程對象的代理,客戶端就象調用本地對象一樣調用該代理,再由代理去跟實際對象聯繫,對於客戶端來說可能根本沒有感覺到調用的東西在網絡另外一端,這實際上就是Web Service的工作原理。另一種情況雖然你所要調用的對象就在本地,但是由於調用非常耗時,你怕影響你正常的操作,所以特意找個代理來處理這種耗時情況,一個最容易理解的就是Word裏面裝了很大一張圖片,在word被打開的時候我們肯定要加載裏面的內容一起打開,但是如果等加載完這個大圖片再打開Word用戶等得可能早已經跳腳了,所以我們可以爲這個圖片設置一個代理,讓代理慢慢打開這個圖片而不影響Word本來的打開的功能。申明一下我只是猜可能Word是這麼做的,具體到底怎麼做的,俺也不知道。

原因二:你不知道怎麼辦過戶手續,或者說除了你現在會幹的事情外,還需要做其他的事情才能達成目的。

對應到我們程序設計的時候就是:除了當前類能夠提供的功能外,我們還需要補充一些其他功能。最容易想到的情況就是權限過濾,我有一個類做某項業務,但是由於安全原因只有某些用戶纔可以調用這個類,此時我們就可以做一個該類的代理類,要求所有請求必須通過該代理類,由該代理類做權限判斷,如果安全則調用實際類的業務開始處理。可能有人說爲什麼我要多加個代理類?我只需要在原來類的方法裏面加上權限過濾不就完了嗎?在程序設計中有一個類的單一性原則問題,這個原則很簡單,就是每個類的功能儘可能單一。爲什麼要單一,因爲只有功能單一這個類被改動的可能性纔會最小,就拿剛纔的例子來說,如果你將權限判斷放在當前類裏面,當前這個類就既要負責自己本身業務邏輯、又要負責權限判斷,那麼就有兩個導致該類變化的原因,現在如果權限規則一旦變化,這個類就必需得改,顯然這不是一個好的設計。

好了,原理的東西已經講得差不多了,要是再講個沒完可能大家要扔磚頭了。呵呵,接下來就看看怎麼來實現代理。

代理模式的實現:

其實代理模式還是很容易實現的,隨便舉個例子,比如你有一個類負責返回員工的薪資信息,如下:

    public class BusinessClass   

    {   

    public double GetPayroll(string employee)   

    {   

    //返回薪資結果   

    return 1000;   

    }   

    }   

    由於薪資信息是公司的機密信息,不是誰都能調用查看,所以我們爲該類做一個代理來做用戶身份的驗證,代碼如下:   

    public class Proxy   

    {   

    private BusinessClass bc;   

    public Proxy(BusinessClass bc)   

    {   

    this.bc=bc;   

    }   

    public double GetPayroll(string user)   

    {   

    //判斷user權限   

    //如果不符合返回null,或者拋出異常   

    if( IsManage(user) )   

    {   

    return bc.GetPayroll(”張三”);   

    }   

    throw new Exception(”你沒有該權限。”);   

    }   

    }   

    注意:代理類需要使用被代理類來做業務邏輯,所以代理類需要包含被代理類的實例,這跟適配器模式是一樣的。   

    到目前爲止目的其實已經達到了,但是現實中我們常常會再爲代理類和被代理類抽象出一個公共接口,如下:   

    public interface IBusinessClass   

    {   

    double GetPayroll(string user);   

    }  

很多人肯定會問爲什麼要抽象這個接口呢?其實抽象接口有一個最大的原因就是約束雙方的行爲!什麼意思呢?其實就是我逼迫Proxy必須實現某些方法,而這些方法恰恰是對外公開的主要業務方法。當然也可以靠程序員自律,但是多一個約束總歸是好的,至少如果沒有實現指定方法我們可以在編譯期就發現錯誤,總比執行時才能發現錯誤要好。另外的原因可能都得歸結到使用接口的好處上去了,這裏不再贅述,自己去查接口的文章介紹了。

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