天天看點

設計模式系列-代理模式

      很久沒有更新設計模式系列的文章了,有了很多熱心朋友的回報,我決定繼續将這個系列趕快寫完,最近由于過年了,有很多相關的事宜要做,是以 沒有時間來寫,也是對大家的說下抱歉,感覺寫文章的時間越來越少了,不過我會努力,盡快将這個系列寫完,與大家共勉,希望大家有什麼意見或建議, 都可以幫我提出來,我好改進,謝謝!。        本文主要是講述設計模式中的結構性模式中的最後一個本系列講述的模式,也是經常用到的模式,代理模式,由于目前我們在很多的技術中都會用到 這個代理模式,是以對我們來說,代理模式是必須掌握的模式之一。我們先來看看代理的思路及原理:         通過上面的圖檔,我們可以看到,通過增加代理來解耦A與C之間的調用,這樣可以封裝原來C調用A的一些相關細節,轉換成C直接調用B中封裝後 的代理方法,則等同于通路A。對于WebService的遠端調用時,如果我們使用添加Web引用的方式,那麼WebService會為我們自動生成代理類的,這個 我這裡就不示範了,包括Castle中的AOP等實作方案都是基于動态代理的機制來實作,當然思路都是這樣的,WCF中也有用到代理的思想。
         前面我們講述了外觀模式中的關于動态代理中的一些實作,當然代理模式與外觀模式的側重點還是有所不同,外觀模式是将衆多細粒度的功能,封 裝成一個粗粒度的功能,供客戶應用程式使用。而代理模式,為其他對象提供一個代理類,通過該代理類來完成目标對象的通路,代理模式相對外觀模式來 說,關鍵不同是在内部,外觀我們知道是将細粒度的功能進行簡單封裝,而代理模式則是内部實作很複雜,其複雜性主要展現在來自如下的幾類複雜性:          可能上述的複雜性還不完整,例如還可能有目前的比較新興的大資料量的虛拟代理或者是智能代理,這方面由于自身不足,是以還無法講述。          本文将會結合舉例說明上述的幾類代理的複雜性的簡單說明,希望能說明清楚。
       a、上篇回顧。        b、摘要。        c、本文大綱。        d、代理模式的特點及使用場景。        e、代理模式的經典實作。        f、代理模式的其他方案。        g、代理模式使用總結。        h、系列進度。        i、下篇預告。
      我們先來看看代理模式的特點及使用場景吧,我們先來看看一個簡單的場景吧:       我們現在要建構一個分布式應用程式,那麼一般在.NET平台下,我們一般會采用WCF或者WebService的方式來釋出應用,不管是平時大家聽 說的SOA架構的實作,還是其他的ESB總線架構等,也無非是二種實作方式,一種是通過API接口程式設計來實作,通過WCF的Remoting或者是其他的方式 來調用遠端服務,另一種是通過WebService的形式來釋出服務,那麼既然有了釋出服務之後,那麼我們之後的操作可能更多關心的是,如果在用戶端使用 這個服務,那麼一般我們可能采用的最常用的方式,就是在用戶端由平台自動生成一個代理或者我們自己寫一個代理類,當然這個代理類可以是通用的代理 類或者是為某些服務單獨寫代理,能夠更友善的使用及提升效率等。       通過上面的說明,那麼我們現在基本上知道了,代理模式的作用展現在哪裡,下面我們來詳細展開說明吧;當我們的一個服務寫的很複雜,但是我們 在用戶端調用的時候,我們又不希望在用戶端使用起來太複雜,這個時候,可能我們想我們通過使用代理類,那麼通過代理類,這個用戶端與遠端的服務類 進行互動過程就變成用戶端與代理類的互動,那麼給客戶的感覺就像服務類就在本地一樣,這樣不但降低了複雜性,而且也降低了耦合性。       那麼一般代理類有什麼要求呢?一般來說代理對象必須實作目标對象定義的一些接口,隻有這樣,用戶端應用程式在使用的時候,通過接口調用來訪 問目标對象的服務,否則就等于引入複雜度,反而沒有解決問題。       使用代理的目的是控制用戶端程式通路目标對象,是以代理必須知道目标對象的類型及目标對象在哪裡,如何通路等都必須明确。       代理對象有的時候也可以是抽象類型,這樣目标類型就可以是未确定的,我們可以通過建立型模式來動态的建立目标對象,當然前提是這些目标對象 是代理對象類型。       代理模式的類圖
設計模式系列-代理模式
下面給出代理模式的經典實作:        我們以如下場景為例,我們現在要實作一個MP3播放的相關功能,一般來說有很多的音頻檔案; 下面我們來看看如何使用代理模式來實作。        (1)、定義用戶端調用的具體的音樂媒體類型類型         (2)、定義用戶端調用的目标對象的接口         (3)、定義具體的目标類型的實作         (4)、定義代理類,該代理類實作了目标類型的接口。          (5)、具體的用戶端調用          上面基本上給出了一個簡單的例子說明,當然具體的代理模式的思路就是這樣了,當然參考上面的類圖來做的話,和我的這個形式差不多,具體的 思想就是為目标類型定義一個接口,然後代理類實作該接口,那麼在代理類中指定具體的目标類型的調用,完成目标類型的調用,傳回調用後的結果,那麼 就等于代理類封裝了目标類型的調用。
      上面我們給出了代理模式的經典實作方案,那麼我們本節看看其他的實作方案,來擴充下我們的方案的使用場景及一些其他的應用場景的情況:        我們給出WebService的示例過程吧:       (1)、 為了說明我們給出的示例過程,我們來建立一個ASP.NET WEB應用程式網站,添加一個WebService服務檔案。       (2)、 選擇添加一個WebService檔案      (3)、添加完後,修改HelloWord方法,添加一個name字段,代表輸入字元串,輸出相應的代碼       (4)、添加完畢後,在浏覽器中檢視       (5)、測試,是否服務正确。運作後的結果應該如下: 置于其他的相應的資訊我就補貼出來了,然後我們将webservice服務釋出出來,通過二種形式來添加代理 1、通過web引用的形式: (1)、先找到webservice服務的釋出位址 <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201354378343.png"></a> (2)、複制位址,并且在要引用該webservice服務的項目中在引用檔案夾中點選右鍵 <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201354415339.png"></a> (3)、将複制的位址,輸入到服務引用的位址欄中 <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201354465683.png"></a> (4)、點選前往,系統就會自動與webservice建立測試連接配接。 <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201354539691.png"></a> 如果沒有出現上述的服務内容,那麼則可能服務沒有釋出,或者服務的引用添加的路徑不對等。點選确定,這個時候,我們來看看代理檔案生成的内容: <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355073188.png"></a> 我們來看看系統為我們自動生成的WEB服務代理的代碼吧: 通過reflactor中的對象浏覽器來檢視系統生成的内容吧: <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355116696.png"></a> 具體的代碼太多了,我這裡就不貼出了,大家可以看看,我這裡給出解析webservice的一些通用的統一代理代碼。 <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355165578.png"></a> <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355207624.png"></a> 這樣就完成通用的Get請求的方式來調用webservice服務。
通過上面的webservice的講述,我想大家對代理模式還是會有些陌生,其實代理模式我們前面也說道,代理是将目标對象的複雜性進行封裝,通過代理來 完成調用,那麼我們針對前面的用戶端調用的目标類型的接口定義,并且目标對象要實作這個接口,代理類也要實作這個接口。 下面來總結下代理模式與外觀模式的差別: 1、外觀模式也是屏蔽複雜性的,但是外觀模式不會實作用戶端調用的目标類型接口。 2、一般用戶端調用外觀模式的方法都是直接調用。 3、代理模式中對用戶端目标對象類型抽象接口具體化了。 4、外觀模式是代理模式中一種特殊的子級模式(廣泛的,非限制性)。 針對前面我們提到過,代理模式中還有将代理類定義成抽象類型,然後完成動态的調用的情況,那麼我們看看我們如何來組織呢? 1、定義多個播放檔案格式對象 <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355248930.png"></a> 新增加上述的3個檔案 2、修改playProxy的代碼如下: <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355285370.png"></a> 3、具體的代理代碼如下:這裡參考AOP的實作機制 <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355331004.png"></a> 4、具體的調用代碼如下: <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/201102/201102201355348331.png"></a> 當然這裡的具體的調用過程還有很多方法可以進行改進的更好,比如在内部的枚舉模式,修改成建立工廠的形式來完成對象的動态建立及調用等。我這裡就 不進行優化了,隻是展示出思路和方案,希望大家提出不同的意見!
建立型 結構型         7、系統架構技能之設計模式-代理模式 行為型         1、系統架構技能之設計模式-指令模式         2、系統架構技能之設計模式-觀察者模式         3、系統架構技能之設計模式-政策模式         4、系統架構技能之設計模式-職責模式         5、系統架構技能之設計模式-模闆模式         6、系統架構技能之設計模式-中介者模式         7、系統架構技能之設計模式-解釋器模式
      下一篇我們将開始講述行為型模式中的“指令模式”該模式是比較常用的模式,也是大衆化的模式,希望能給大家說明清楚,對我自身來說也是一個 不小的挑戰,歡迎大家拍磚。

本文轉自 hot的fans  51CTO部落格,原文連結:http://blog.51cto.com/2435232/504317

繼續閱讀