天天看點

設計模式系列-擴充卡模式

        通過上篇的簡單講解,我們知道了,組合模式意圖是通過整體與局部之間的關系,通過樹形結構的形式進行組織複雜對象,屏蔽對象内部的細節,對 外展現統一的方式來操作對象,是我們處理更複雜對象的一個手段和方式。本文以查詢控件為例,說明了,查詢控件内部的組成元素,及如何操作内部的組 成元素,包括添加元素,删除和處理相應事件的Handler,當然組合模式的作用遠比這些強大,後面我們肯定會在一些執行個體代碼中運用到組合模式的。組合 模式如果在條件允許的情況下,我們盡量使用組合模式來處理複雜對象,遠比通過繼承出來的對象來的有效。         組合模式-強調的是如何組織整體和局部之間的結構,将整體和局部之間的關系,通過樹形這樣的結構來組織這種對象組合的結構關系。         組合模式的适用場景:         1、我們期望操作一個複雜對象和操作一個組成這個複雜對象内部的簡單對象一樣操作的時候,我們可以考慮對象組合。         2、當一個對象由多個簡單對象組成,并且它又可能是其他對象的一個組成部分,這種情況下,組合模式是比較好的選擇。
        本篇将會講述結構型模式中的經典模式-擴充卡模式,也是項目中經常使用的模式之一,我們現在開發一個系統的時候,也許會遇到各式各樣的要求,我們要求和現有的系統 進行內建,或者是我們直接開發一個系統,或者是我們修改已有的系統達到滿足現有需求的要求。是以一般來說,每種情況,我們都有自己的應對方案。我們來看看項目中的幾種 可能情況: <a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/Windows-Live-Writer/913ef3d2f485_79FA/image_2.png"></a> 通過上面的幾種情況,我們知道,開發一個新系統吧,成本和時間的投入較高,如果說我們舊系統目前運作的非常穩定,并且投入的成本非常高,我們既想繼續使用舊系統的功 能,又想滿足新系統的需求,這個時候,我們怎麼做呢?可能比較好的方式就是把舊系統通過擴充卡來轉換成新接口的調用形式,完成适配服務。當然本文也是主要針對這個思 路,展開去講述擴充卡模式的一些用法,當然我這裡可能講解了擴充卡模式的一些普遍用法,還有一些比較特殊的用法,需要大家多多指出,向大夥學習了。         本文主要講述下面的幾個部分的内容:         1、擴充卡模式的使用場景。         2、擴充卡模式的經典實作。         3、多擴充卡的封裝。         4、其他情況的考慮。
       a、上篇回顧。        b、摘要。        c、本文大綱。        d、擴充卡模式的特點及使用場景。        e、擴充卡模式的經典實作。        f、擴充卡模式的其他方案。        g、擴充卡模式使用總結。        h、系列進度。        i、下篇預告。
        擴充卡模式主要解決的問題就是我們要調用的接口類型,無法滿足我們新系統的使用需求,這時候,我們需要将舊系統的接口,通過擴充卡進行轉配,達到支援新接口調用 的目的。對于這樣的要求,我們通過擴充卡就可以完成,當然如果有多個接口需要轉配,那麼我們就需要為每一個接口提供一個擴充卡去完成轉換的工作。當然具體的調用過程, 我們可以進行相應的封裝。達到比較通用的方式去調用擴充卡,完成适配服務。我們來看看适配的過程。
       我們根據上面的擴充卡的特點的介紹中,我們來分析下擴充卡模式的幾類比較适用的使用場景:        1、我們在使用第三方的類庫,或者說第三方的API的時候,我們通過擴充卡轉換來滿足現有系統的使用需求。        2、我們的舊系統與新系統進行內建的時候,我們發現舊系統的資料無法滿足新系統的需求,那麼這個時候,我們可能需要擴充卡,完成調用需求。        3、我們在使用不同資料庫之間進行資料同步。(我這裡隻是分析的是通過程式來說實作的時候的情況。還有其他的很多種方式[資料庫同步])。
      我們本節給出擴充卡模式的經典實作代碼,我們這裡結合項目中的查詢服務來進行說明,舊系統中提供一個查詢服務方法Query();但是我新系統定義底層的資料通路服務層 的時候,卻是使用的GetList()方法,并且将之前的傳回結果集合進行包裝成泛型的形式來進行。我們這裡給出相關的示例代碼,大家就能清楚這個使用過程了,當然我們這裡給 出類擴充卡和對象擴充卡2種實作的方式,通過不同的實作思路,我們最後總結下,這2種形式的優缺點:    針對上面描述的接口的轉配過程,我們給出示例代碼:    舊系統的查詢服務     public class Query :IQuery      {          public object Query()          {              return new object();          }      } 新系統的查詢服務接口:     public interface ISelect          object GetList();  通過類擴充卡完成轉配操作:     public class QueryAdapter : Query, ISelect          public object GetList()              return base.Query();    具體的調用測試代碼如下:     class Program          static void Main(string[] args)              ISelect adapter = new QueryAdapter();             object o= adapter.GetList();             System.Threading.Thread.Sleep(10000);     public class QueryAdapter :  ISelect          private Query query = new Query();             return query.Query();          } 上面我們就完成了經典的擴充卡模式的簡單實作,當然上面也沒有考慮通用性等各方面的内容,隻是給出了一個大概的實作,當然對于上面的擴充卡的建立過程,我們可以通過前 面講述的建立型模式中的幾個實作方案,進行相應的改進。

           上面給出了擴充卡模式的經典實作,參考其他篇講述的方式,我們給出擴充卡模式的其他演變方式

        我們在項目中,可能需要對一批的舊系統的接口進行封裝,這個時候我們可以通過配置檔案的方式配置擴充卡。         例如我們上面的查詢,可能我現在對于XML檔案的查詢方法與資料庫的查詢方法2個舊的查詢服務進行封裝,然後我在實際的項目中,通過配置來選擇我使用哪個查詢方法 完成查詢服務,通過傳入參數,或者是配置節資訊來進行控制。我們來看看相關的示例代碼:         舊系統定義的查詢服務接口:     public interface IQuery          object Query();          XML查詢和資料庫方式的實作:     public class XMLQuery : IQuery              throw new NotImplementedException();      public class DbQuery : IQuery      新查詢服務接口:     具體的擴充卡代碼實作:     public class XMLAdapter : ISelect          private XMLQuery query = new XMLQuery();      public class DbAdapter : ISelect          private DbQuery query = new DbQuery();     工廠來負責建立舊系統接口的服務的對象。     public class AdapterFactory          public static ISelect CreateAdapter()              return (ISelect)Activator.CreateInstance(Type.GetType(""));    具體的調用測試代碼:             ISelect select = AdapterFactory.CreateAdapter();             object o= select.GetList(); 
   舊系統定義的查詢服務接口:     工廠來負責建立舊系統接口的服務的對象。     public class OldFactory           public static IQuery CreateQuery()           {               return (IQuery)Activator.CreateInstance(Type.GetType(""));           }      具體的通用擴充卡代碼實作:     public class ComAdapter : ISelect          IQuery query = OldFactory.CreateQuery();     将擴充卡的建立過程通過工廠來實作,達到解耦的目的:             return new ComAdapter ();     具體的調用測試代碼:
        我們上面給出了擴充卡模式的簡單講解,其實擴充卡模式的應用還是很廣泛的,上面也分析了擴充卡模式的使用場景和特點,那麼其實本篇還沒有給出執行個體講述擴充卡之間 的轉換:                上面我們講述了2中比較通用的形式來調用擴充卡,還有其他的方式,比如通過字典的方式,然後通過屬性索引的形式來使用擴充卡,我上面給出了一些比較簡單的通用的使 用思路,當然還有很多更好的方式,希望大家指出,向大夥學習了。我們這裡給出擴充卡之間互相轉換的情況,有的時候,我們發現2個擴充卡之間也需要進行相應的轉配,例如 我們上面的資料庫和XML檔案的查詢接口,例如有的時候,我需要把XML檔案的資料轉換到資料庫中,或者把資料庫中的資料儲存成XML形式,這個時候,我們就需要定義一個對 象,來完成相應的擴充卡之間的适配。 了,下篇會講橋模式的時候,會給出這部分的具體實作,還請關注!我相信通過上面的講述,大家對這個擴充卡模式有了一定的映像,我們上面沒有講述類擴充卡和對象擴充卡之 間的差別,這裡補充講解一下:       對象擴充卡:不是通過繼承的方式,而是通過對象組合的方式來進行處理的,我們隻要學過OO的設計原則的都知道,組合相比繼承是推薦的方式。       類擴充卡:通過繼承的方式來實作,将舊系統的方法進行封裝。對象擴充卡在進行擴充卡之間的轉換過程中,無疑類擴充卡也能完成,但是依賴性會加大,并且随着适配要求的靈活性,可能通過繼承膨脹的難以控制。       一般來說類擴充卡的靈活性較差,對象擴充卡較靈活,是我們推薦的方式,可以通過依賴注入的方式,或者是配置的方式來做。類擴充卡需要繼承自要适配的舊系統的類,無疑這不是一個好的辦法。

版權聲明:原創作品,如需轉載,請注明出處。否則将追究法律責任

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