1. 程式人生 > >設計模式學習筆記-工廠方法模式

設計模式學習筆記-工廠方法模式

定義:

建立一個工廠介面和建立多個工廠實現類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的程式碼。

解決問題:

簡單工廠模式的問題,類的建立依賴工廠類,也就是說,如果想要拓展程式,必須對工廠類進行修改,這違背了閉包原則

動機(Motivate)
           在軟體系統的構建過程中,經常面臨著“某個物件”的建立工作:由於需求的變化,這個物件(的具體實現)經常面臨著劇烈的變化,但是它卻擁有比較穩定的介面

      如何應對這種變化?如何提供一種“封裝機制”來隔離出“這個易變物件”的變化,從而保持系統中“其他依賴物件的物件”不隨著需求改變而改變?

 模式的組成,可以看出,在工廠方法模式的結構圖有以下角色:
          (1)、抽象工廠角色(Creator): 
充當抽象工廠角色,定義工廠類所具有的基本的操作,任何具體工廠都必須繼承該抽象類。
          (2)、具體工廠角色(ConcreteCreator):充當具體工廠角色,該類必須繼承抽象工廠角色,實現抽象工廠定義的方法,用來建立具體產品。
          (3)、抽象產品角色(Product):

充當抽象產品角色,定義了產品型別所有具有的基本操作,具體產品必須繼承該抽象類。
          (4)、具體產品角色(ConcreteProduct):充當具體產品角色,實現抽象產品類對定義的抽象方法,由具體工廠類建立,它們之間有一一對應的關係。


意圖(Intent)
         
定義一個用於建立物件的介面,讓子類決定例項化哪一個類。Factory Method使得一個類的例項化延遲到子類。            

實現:

工廠方法模式之所以可以解決簡單工廠的模式,是因為它的實現把具體產品的建立推遲到子類中,此時工廠類不再負責所有產品的建立,而只是給出具體工廠必須實現的介面,這樣工廠方法模式就可以允許系統不修改工廠類邏輯的情況下來新增新產品,這樣也就克服了簡單工廠模式中缺點。

 實現思路:

【簡單工廠模式】的問題是:如果有新的需求就需要修改工廠類裡面建立產品物件例項的那個方法的實現程式碼,在面向物件設計一個原則就是哪裡有變化,我就封裝哪裡。還有另外兩個大的原則,其一是:面向抽象程式設計,細節和高層實現都要依賴抽象,第二個原則是:多組合,少繼承。這三個原則是最根本的原則,學習設計模式必須以這三個原則為基點,否則都是枉然。根據這三大原則又衍生出來6個具體的原則,分別是【單一職責原則】,【里氏替換原則】,【依賴倒置原則】,【介面隔離原則】、【迪米特法則】和【開閉原則】,既然工廠類有變化,我們就封裝它,面向抽象程式設計,我們先抽象出一個工廠基類,然後,每個需求就實現一個具體的工廠類,這樣我們就符合了【開閉原則OCP】,讓一個工廠生產一款產品,並一一對應。我們把具體產品的建立推遲到子類中

   /// <summary>
    /// 菜抽象類
    /// </summary>
    public abstract class Food
    {
        // 輸出點了什麼菜
        public abstract void Print();
    }

    /// <summary>
    /// 西紅柿炒雞蛋這道菜
    /// </summary>
    public class TomatoScrambledEggs : Food
    {
        public override void Print()
        {
            Console.WriteLine("西紅柿炒蛋好了!");
        }
    }

    /// <summary>
    /// 土豆肉絲這道菜
    /// </summary>
    public class ShreddedPorkWithPotatoes : Food
    {
        public override void Print()
        {
            Console.WriteLine("土豆肉絲好了");
        }
    }

    /// <summary>
    /// 抽象工廠類
    /// </summary>
    public abstract class Creator
    {
        // 工廠方法
        public abstract Food CreateFoddFactory();
    }

    /// <summary>
    /// 西紅柿炒蛋工廠類
    /// </summary>
    public class TomatoScrambledEggsFactory:Creator
    {
        /// <summary>
        /// 負責建立西紅柿炒蛋這道菜
        /// </summary>
        /// <returns></returns>
        public override Food CreateFoddFactory()
        {
            return new TomatoScrambledEggs();
        }
    }

    /// <summary>
    /// 土豆肉絲工廠類
    /// </summary>
    public class ShreddedPorkWithPotatoesFactory:Creator
    {
        /// <summary>
        /// 負責建立土豆肉絲這道菜
        /// </summary>
        /// <returns></returns>
        public override Food CreateFoddFactory()
        {
            return new ShreddedPorkWithPotatoes();
        }
    }

    /// <summary>
    /// 客戶端呼叫
    /// </summary>
    class Client
    {
        static void Main(string[] args)
        {
            // 初始化做菜的兩個工廠()
            Creator shreddedPorkWithPotatoesFactory = new ShreddedPorkWithPotatoesFactory();
            Creator tomatoScrambledEggsFactory = new TomatoScrambledEggsFactory();

            // 開始做西紅柿炒蛋
            Food tomatoScrambleEggs = tomatoScrambledEggsFactory.CreateFoddFactory();
            tomatoScrambleEggs.Print();

            //開始做土豆肉絲
            Food shreddedPorkWithPotatoes = shreddedPorkWithPotatoesFactory.CreateFoddFactory();
            shreddedPorkWithPotatoes.Print();

            Console.Read();
        }
    }  

Factory Method模式的幾個要點

  Factory Method模式主要用於隔離類物件的使用者和具體型別之間的耦合關係。面對一個經常變化的具體型別,緊耦合關係會導致軟體的脆弱。

  Factory Method模式通過面向物件的手法,將所要建立的具體物件工作延遲到子類,從而實現一種擴充套件(而非更改)的策略,較好地解決了這種緊耦合關係。
 

      Factory Method模式解決“單個物件”的需求變化;

      AbstractFactory模式解決“系列物件”的需求變化;

      Builder模式解決“物件部分”的需求變化;

        3.1】、工廠方法模式的優點:

           (1)、 在工廠方法中,使用者只需要知道所要產品的具體工廠,無須關係具體的建立過程,甚至不需要具體產品類的類名。

           (2)、在系統增加新的產品時,我們只需要新增一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了“開閉原則”。

        3.2】、工廠方法模式的缺點:

           (1)、每次增加一個產品時,都需要增加一個具體類和物件實現工廠,是的系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。

        3.3】、工廠方法模式使用的場景:

            (1)、一個類不知道它所需要的物件的類。在工廠方法模式中,我們不需要具體產品的類名,我們只需要知道建立它的具體工廠即可。

            (2)、一個類通過其子類來指定建立那個物件。在工廠方法模式中,對於抽象工廠類只需要提供一個建立產品的介面,而由其子類來確定具體要建立的物件,在程式執行時,子類物件將覆蓋父類物件,從而使得系統更容易擴充套件。

            (3)、將建立物件的任務委託給多個工廠子類中的某一個,客戶端在使用時可以無須關心是哪一個工廠子類建立產品子類,需要時再動態指定。

四、.NET中實現了工廠方法的類

.NET 類庫中也有很多實現了工廠方法的類,例如Asp.net中,處理程式物件是具體用來處理請求,當我們請求一個*.aspx的檔案時,此時會對映到System.Web.UI.PageHandlerFactory類上進行處理,而對*.ashx的請求將對映到System.Web.UI.SimpleHandlerFactory類中(這兩個類都是繼承於IHttpHandlerFactory介面的),關於這點說明我們可以在“C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Web.Config”檔案中找到相關定義,具體定義如下:

<add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True"/>
 <add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True"/>
<add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True"/>

總結:

工廠方法模式通過面向物件程式設計中的多型性來將物件的建立延遲到具體工廠中,從而解決了簡單工廠模式中存在的問題,也很好地符合了開放封閉原則(即對擴充套件開發,對修改封閉)。

 

JAVA:

 

參考文獻:

http://www.cnblogs.com/zhili/p/FactoryMethod.html

https://www.cnblogs.com/PatrickLiu/p/7567880.html