天天看點

系統架構技能之設計模式-抽象工廠模式

        上篇我們主要講述了簡單工廠模式和工廠模式。并且分析了每種模式的應用場景和一些優缺點,我們現在來回顧一下:

        簡單工廠模式:一個工廠負責所有類型對象的建立,不支援無縫的新增新的類型對象的建立。

        工廠模式:多個工廠負責多個類型對象的建立,每個工廠隻負責具體類型對象的建立,支援無縫的新增類型對象的建立,需要實作工廠接口類和具體的類型對象類。

        我們來簡單的對比下這2個模式的優缺點:

模式名稱 優點 缺點 簡單工廠模式 一個工廠負責所有對象的建立,簡單靈活 不符合高内聚的原則,不支援無縫的擴充 工廠模式 可以無縫的新增類型,每個工廠職責單一,符合高内聚的原則 工廠類太多,難以維護。

        工廠模式,很優雅的解決了應用程式使用對象時的無限new()的操作,同時降低了系統應用之間的耦合性,提高了系統的可維護性和适應性。

        本文主要是針對建立型模式中的抽象工廠模式進行講述,抽象工廠模式是在簡單工廠模式的基礎上擴充而成的新模式,将簡單工廠中的對象的建立過程進行了很優雅的動态配置來完成無

縫的擴充,當然通過一些擴充,可以建構出可支援動态新增或者删除對象的抽象工廠模式。本文将會給出具體的實作方案,相比工廠模式,抽象工廠模式是一個工廠負責多個對象的建立,傳回

的具體的類型是這個對象的抽象類型。這樣,在用戶端引用的時候隻需要使用這個工廠傳回的對象類型,抽象工廠會自動根據對象的類型動态的建立這個類型對象的執行個體。大體的過程如下:

上面的圖檔呢,主要是針對經典的抽象工廠模式給出了一個實作草圖的模拟,而我們在實際的項目中可能并不希望給出這麼多的抽象工廠工廠實作,我隻想給出一個通用的抽象 工廠實作,通過靜态方法直接調用,傳回我想要的對象類型的執行個體,而且這個對象類型是可以動态配置的,那麼我們如何做到呢?這就是本篇需要讨論的實作方案。本篇将會從 以下幾點進行講述抽象工廠模式: 1、抽象工廠模式的簡單執行個體代碼-這裡給出的是經典的抽象工廠模式執行個體代碼。我們從經典的執行個體代碼中可以看出這個工廠模式的一些缺點。

          2、根據經典工廠模式的缺點,我們給出改進的方案,進一步給出項目中可以使用的通用方案實作。

          3、給出上篇中的通過委托來實作的工廠模式方案。

          4、通過特性+反射的形式來動态的建立對象。

       a、上篇回顧。

       b、摘要。

       c、本文大綱。

       d、抽象工廠模式的特點及使用場景。

       e、抽象工廠模式的實作方案。

       f、抽象工廠模式使用總結。

       g、系列進度。

       h、下篇預告。

        抽象工廠可以說是三類工廠模式中使用最廣泛的,也是最受大家喜愛的模式之一,因為抽象工廠模式解決了一系列互相依賴的對象或者有組合關系的對象的建立過程。舉個簡單的例子來

說,我們以電腦的顯示卡和風扇來說吧,我們知道顯示卡一般在玩遊戲的時候,由于渲染圖形會産生大量的熱量,如果沒有好的風扇那麼可能無法達到好的散熱的效果,這個時候我們可以把顯示卡和

風扇的建立放在一個抽象工廠中進行建立,因為這2個對象是具有依賴關系的對象,那麼我們來給出這個例子的完整執行個體代碼:

        先看看2個對象類型的接口和抽象工廠的接口定義

    /// <summary>      /// 定義顯示卡抽象對象接口      /// </summary>      public interface IDisplayCard      {      }     /// 定義顯示卡風扇抽象對象接口      public interface IDisplayFan      /// 定義顯示卡裝置抽象工廠接口      public  interface IAbstractDriveFactory          IDisplayCard CreateDisplayCard();         IDisplayFan CreateDisplayFan(); 

     我們來看看具體類型的實作和抽象工廠的具體實作。

    /// 定義華碩顯示卡的具體對象      public class DisplayCardAsus : IDisplayCard 
    /// 華碩顯示卡配套風扇      public class DisplayFanAsus : IDisplayFan 
    /// 華碩顯示卡具體實作工廠      public class DriveFactoryAsus : IAbstractDriveFactory          IDisplayCard CreateDisplayCardAsus()          {              return new DisplayCardAsus();          }         IDisplayFan CreateDisplayFanAsus()              return new DisplayFanAsus();          } 

        通過上面的代碼,我們給出了抽象工廠的一個經典執行個體的實作方案,當然這不是我們開發中使用的實際形式,那麼實際我們在項目中如何使用這個抽象工廠模式呢?我們一般是改進的方

案去使用這個抽象工廠模式,我們如何改進呢?對于目前的,如果我不光建立顯示卡裝置和配套的風扇裝置,我還想建立其他的類型的東西,這時候可能我們定義的抽象工廠就無法滿足具有互相

依賴或者組合關系的對象類型執行個體的建立工作了,那麼我們如何改進呢,這就是下面要講述的幾類方案。

我們先給出基于上面的經典抽象工廠的一個改進的方案,可以支援動态配置的抽象工廠,一個工廠負責動态的建立一些列的可動态配置的對象清單,我們如何做呢,我想一提到配置。大家都知道要麼是通過XML檔案來實作或者是通過泛型集合來做。我們這裡可以提供的方案是這樣的,通過工廠初始化時從配置檔案中讀取配置項,構造一個字典,然後從這個字典中查詢要建立的類型是否在字典中,如果在字典中存在則建立這個類型的對象,否則傳回NULL,我們這裡通過泛型來實作。

我們來看看具體的代碼實作吧:

    /// 定義抽象工廠接口      public  interface IAbstractFactory          /// <summary>          /// 通用的泛型對象建立工廠          /// </summary>          /// <typeparam name="T"></typeparam>          /// <returns></returns>          T Create<T>();  給出具體的實作這個接口的抽象工廠類    /// <summary>     /// 具體的通用工廠實作     /// </summary>     public  class AbstractFactory : IAbstractFactory     {         private static readonly IDictionary<Type, Type> instances = null;        public static AbstractFactory()         {             //從具體的配置項中讀取,從配置檔案中讀取或者通過某個方法來寫死實作等。             //這裡推薦的做飯是從配置檔案中讀取。             instances = new Dictionary<Type, Type>();             instances.Add(Type.GetType(""), Type.GetType(""));         }         public T Create<T>()             if (!instances.ContainsKey(typeof(T)))                 return default(T);            Type typeInstance = instances[typeof(T)];            T obj = (T)Activator.CreateInstance(typeInstance);            return obj;     }

通過上面給出的代碼,基本上可以滿足一般項目的需求,大家當然有好的思路和建議也可以提出,給出更好的改進方案,下面我給出大概的配置檔案格式,其實就是父子級節點,父級節點是負責建立的工廠

類,那麼這個父節點下的子節點就是工廠要建立的具體的對象類型。

<a href="http://images.cnblogs.com/cnblogs_com/hegezhou_hot/Windows-Live-Writer/592b39ea7052_8409/image_6.png"></a> 上圖中描述的思路,我們大概知道了,對應這樣的一個支援多個具有依賴關系或者組合關系的對象的動态抽象工廠的實作,那麼如果我們想實作支援多個具有依賴關系或者組合 關系的不同的建立形式的通用建立工廠時,我們如何來做呢?同上面的思路,隻不過我們外部需要再添加一個字典,負責類型和抽象工廠的映射,即抽象工廠可以建立的字典列 表及抽象工廠具體執行個體類型之間的鍵值對關系,或者通過配置檔案來組織父子級的關系。我們大概的看下配置檔案的組織吧: &lt;?xml version="1.0" encoding="utf-8" ?&gt;  &lt;AbstractFactory&gt;      &lt;FactorySections&gt;          &lt;FactorySection name="ProductFactory" type="DesignPattern.ProductFactory"&gt;              &lt;ObjectInstance name="" type=""/&gt;          &lt;/FactorySection&gt;          &lt;FactorySection name="FoodFactory" type="DesignPattern.FoodFactory"&gt;          &lt;FactorySection name="BookFactory" type="DesignPattern.BookFactory"&gt;      &lt;/FactorySections&gt;  &lt;/AbstractFactory&gt;

          那麼具體的抽象工廠的代碼又如何組織呢?如下形式:

    /// 具體的通用工廠實作      public  class AbstractFactory : IAbstractFactory          /// 工廠與工廠能夠建立的對象類型字典之間的映射字典          private static readonly IDictionary&lt;Type, Dictionary&lt;Type, Type&gt;&gt; typeMapper = null;          private Type factoryType = null;
        public static AbstractFactory()              //從具體的配置項中讀取,從配置檔案中讀取或者通過某個方法來寫死實作等。              //這裡推薦的做飯是從配置檔案中讀取。              //根據配置檔案中的ObjectInstance 節點放在對應的工廠下的字典中              //每個工廠節點FactorySection 就會建立一個字典,并且将這個工廠能夠建立的類型放在這個字典中              typeMapper = new Dictionary&lt;Type, Dictionary&lt;Type, Type&gt;&gt;();          public  AbstractFactory(string typeName)              this.factoryType = Type.GetType(typeName);          public T Create&lt;T&gt;()              if(typeMapper.ContainsKey(this.factoryType))                  return default(T);             Dictionary&lt;Type, Type&gt; instances = typeMapper[this.factoryType];             if (!instances.ContainsKey(typeof(T)))              Type typeInstance = instances[typeof(T)];             T obj = (T)Activator.CreateInstance(typeInstance);             return obj;  通過上面的代碼我們就給出了一個通用的抽象工廠的可行的解決方案。

          我們先要定義一個委托:

public delegate string DelegateFunctionHandler(string userName); 基于這個委托的工廠實作方案
    public  class DegelateFactory           private DelegateFunctionHandler handler = null;         public static  DelegateFunctionHandler Create()              if (handler == null)                  handler = new DelegateFunctionHandler(this.Test);             return handler;          public string Test(string name)              return "Test!"; 

           工廠傳回一個委托類型的對象,當然我上面為了簡單給出的test方法其實就是工廠内部的方法,當然這裡還可以進行相應的改進,也可以通過配置檔案來完成,通過配置檔案把相應相

應的委托事件方法,通過配置來通過工廠動态的建立。下面給出個思路吧,具體的實作我就不貼出來了:

         通過上面的實作方式和思路,我們來對比一下抽象工廠、工廠模式、簡單工廠模式之間的差異和相同點。

         相同點:

          1、都是為客戶調用程式與具體的對象類型之間提供了一個解耦作用,這裡怎麼說呢?其實就是應用程式不關心這個對象是怎麼出來的,隻關系如何使用這個對象,而且以後就算對象發生變化,那麼也不需 要修改使用者應用程式的代碼。          2、提高了程式的可維護性和低耦合性。

         異同點:

         1、簡單工廠模式:是簡單的一些列沒有任何依賴關系的對象的建立,内部包含複雜的邏輯關系,一半是通過配置或者參數來進行建立對象,适合對象類型不多,并且不會經常新增的情況下。                工廠模式:每個工廠負責具體類型對象的建立,提供了可以動态新增産品類型的建立,并不需要修改現有的程式就可以無縫的新增産品類型。                抽象工廠模式:支援動态的新增對象類型和新增工廠類型,實作多種依賴關系的對象或者組合關系的建立,适合現有項目中的對象建立過程。          2、簡單工廠模式:内部邏輯複雜,不符合高内聚的原則。                工廠模式:每次新增一個對象類型,就必須新增一個對應的建立工廠,無疑這是一個非常大的工作量。                抽象工廠模式:是在簡單工廠模式的基礎上經過改進具有前2個模式的優點,又屏蔽了他們的一些缺點。

當然我們在具體的項目中,還是需要具體的情況具體分析,一般情況下,我們對于這種資料庫平滑遷移時,簡單工廠可能比其他2類工廠更容易做,也很靈活。

      建立型         4、系統架構技能之設計模式-建立者模式         5、系統架構技能之設計模式-原型模式         結構型         1、系統架構技能之設計模式-組合模式         2、系統架構技能之設計模式-外觀模式         3、系統架構技能之設計模式-擴充卡模式         4、系統架構技能之設計模式-橋模式         5、系統架構技能之設計模式-裝飾模式         6、系統架構技能之設計模式-享元模式         7、系統架構技能之設計模式-代理模式         行為型         1、系統架構技能之設計模式-指令模式         2、系統架構技能之設計模式-觀察者模式         3、系統架構技能之設計模式-政策模式         4、系統架構技能之設計模式-職責模式         5、系統架構技能之設計模式-模闆模式         6、系統架構技能之設計模式-中介者模式         7、系統架構技能之設計模式-解釋器模式
       下篇将會針對建立者模式進行講述,該模式也是建立型模式中最複雜的設計模式之一,該 模式是對一個對象的各個建立部分進行劃分,最後建立出完整的對象,當然這裡面的實作方式可以說還是 本文轉自 hot的fans  51CTO部落格,原文連結: http://blog.51cto.com/2435232/440216