C#設計模式學習筆記:(2)工廠方法模式

    本筆記摘抄自:http://www.javashuo.com/article/p-gfqxtqtz-hg.html,記錄一下學習過程以備後續查用。html

    1、引言編程

    接上一篇C#設計模式學習筆記:簡單工廠模式(工廠方法模式前奏篇),經過簡單工廠模式的瞭解,它的缺點就是隨着需求的變化咱們要不停地修改工廠裏設計模式

面的方法的代碼,需求變化越多,裏面的if--else也越多,這樣就會形成簡單工廠的實現邏輯過於複雜。ide

    依設計原則裏的開閉原則--對增長代碼開放,對修改代碼關閉,咱們不能老是這樣修改簡單工廠裏面的方法。post

    下面看看工廠方法模式是如何解決該問題的?學習

    2、工廠方法模式介紹ui

   工廠方法模式:英文名稱--Factory Method Pattern;分類--建立型。atom

    2.一、動機(Motivate)url

    在軟件系統的構建過程當中,常常面臨着「某個對象」的建立工做:因爲需求的變化,這個對象(的具體實現)常常面臨着劇烈的變化,可是它卻擁有比spa

較穩定的接口。

    如何應對這種變化?如何提供一種「封裝機制」來隔離出「這個易變對象」的變化,從而保持系統中「其餘依賴對象的對象」不隨着需求改變而改變?

    2.二、意圖(Intent)

    定義一個用於建立對象的接口,讓子類決定實例化哪個類。Factory Method使得一個類的實例化延遲到子類。--《設計模式》GoF

    2.三、結構圖(Structure)

    2.四、模式的組成

    從上圖能夠看出,在工廠方法模式的結構圖有如下角色:

    1)抽象工廠角色(Creator):充當抽象工廠角色,定義工廠類所具備的基本的操做,任何具體工廠都必須繼承該抽象類。

    2)具體工廠角色(ConcreteCreator):充當具體工廠角色,該類必須繼承抽象工廠角色,實現抽象工廠定義的方法,用來建立具體產品。

    3)抽象產品角色(Product):充當抽象產品角色,定義了產品類型全部具備的基本操做,具體產品必須繼承該抽象類。

    4)具體產品角色(ConcreteProduct):充當具體產品角色,實現抽象產品類對定義的抽象方法,由具體工廠類建立,它們之間有一一對應的關係。

    2.五、工廠方法模式代碼實現

    面向對象設計三大原則:

    1)哪裏有變化就封裝哪裏。

    2)面向抽象編程,細節和高層實現都要依賴抽象。

    3)多組合,少繼承。

    這三大原則是最根本的原則,學習設計模式必須以這三個原則爲基點,不然都是枉然。根據這三大原則又衍生出來6個具體的原則,分別是單一職責

原則、開閉原則、里氏替換原則、依賴倒置原則、接口隔離原則、迪米特法則。

    既然工廠類有變化,咱們就封裝它,面向抽象編程。咱們先抽象出一個工廠基類,而後每一個需求都實現一個具體的工廠類,這樣咱們就符合了開閉原

,讓一個工廠生產一款產品,並一一對應。具體產品的建立推遲到子類中,此時工廠類(基類)再也不負責全部產品的建立,而只是給出具體工廠必須

實現的接口,這樣工廠方法模式就能夠容許系統不修改工廠類邏輯的狀況下來添加新產品,也就克服了簡單工廠模式中缺點。

    下面是工廠方法模式的實現代碼:

    class Program
    {
        /// <summary>
        /// 汽車抽象類
        /// </summary>
        public abstract class Car
        {
            //開始行駛
            public abstract void Go();
        }

        /// <summary>
        /// 紅旗汽車
        /// </summary>
        public class HongQiCar : Car
        {
            public override void Go()
            {
                Console.WriteLine("紅旗汽車生產中。");
            }
        }

        /// <summary>
        /// 奧迪汽車
        /// </summary>
        public class AoDiCar : Car
        {
            public override void Go()
            {
                Console.WriteLine("奧迪汽車生產中。");
            }
        }

        /// <summary>
        /// 抽象工廠類
        /// </summary>
        public abstract class Factory
        {
            //工廠方法
            public abstract Car CreateCar();
        }

        /// <summary>
        /// 紅旗汽車工廠類
        /// </summary>
        public class HongQiCarFactory : Factory
        {
            /// <summary>
            /// 負責生產紅旗汽車
            /// </summary>
            /// <returns></returns>
            public override Car CreateCar()
            {
                return new HongQiCar();
            }
        }

        /// <summary>
        /// 奧迪汽車工廠類
        /// </summary>
        public class AoDiCarFactory : Factory
        {
            /// <summary>
            /// 負責建立奧迪汽車
            /// </summary>
            /// <returns></returns>
            public override Car CreateCar()
            {
                return new AoDiCar();
            }
        }

        static void Main(string[] args)
        {
            #region 工廠方法模式
            //初始化建立汽車的兩個工廠
            Factory hongQiCarFactory = new HongQiCarFactory();
            Factory aoDiCarFactory = new AoDiCarFactory();

            //生產一輛紅旗汽車
            Car hongQi = hongQiCarFactory.CreateCar();
            hongQi.Go();

            //生產一輛奧迪汽車
            Car aoDi = aoDiCarFactory.CreateCar();
            aoDi.Go();

            Console.Read();
            #endregion
        }
    }
View Code

    運行結果以下:

    使用工廠方法實現的系統,若是系統須要添加新產品時,咱們能夠利用多態性來完成系統的擴展,對於抽象工廠類和具體工廠中的代碼都不須要作任

何改動。假如咱們想生產奔馳車,咱們只需從Car抽象類下繼承一個BenChiCar類、在Factory抽象類下繼承一個「奔馳」的工廠類BenChiCarFactory就可

以實現了:

    class Program
    {
        /// <summary>
        /// 汽車抽象類
        /// </summary>
        public abstract class Car
        {
            //開始行駛
            public abstract void Go();
        }

        /// <summary>
        /// 紅旗汽車
        /// </summary>
        public class HongQiCar : Car
        {
            public override void Go()
            {
                Console.WriteLine("紅旗汽車生產中。");
            }
        }

        /// <summary>
        /// 奧迪汽車
        /// </summary>
        public class AoDiCar : Car
        {
            public override void Go()
            {
                Console.WriteLine("奧迪汽車生產中。");
            }
        }

        /// <summary>
        /// 奔馳汽車
        /// </summary>
        public class BenChiCar : Car
        {
            public override void Go()
            {
                Console.WriteLine("奔馳汽車生產中。");
            }
        }

        /// <summary>
        /// 抽象工廠類
        /// </summary>
        public abstract class Factory
        {
            //工廠方法
            public abstract Car CreateCar();
        }

        /// <summary>
        /// 紅旗汽車工廠類
        /// </summary>
        public class HongQiCarFactory : Factory
        {
            /// <summary>
            /// 負責生產紅旗汽車
            /// </summary>
            /// <returns></returns>
            public override Car CreateCar()
            {
                return new HongQiCar();
            }
        }

        /// <summary>
        /// 奧迪汽車工廠類
        /// </summary>
        public class AoDiCarFactory : Factory
        {
            /// <summary>
            /// 負責建立奧迪汽車
            /// </summary>
            /// <returns></returns>
            public override Car CreateCar()
            {
                return new AoDiCar();
            }
        }

        /// <summary>
        /// 奔馳汽車工廠類
        /// </summary>
        public class BenChiCarFactory : Factory
        {
            /// <summary>
            /// 負責生產奔馳汽車
            /// </summary>
            /// <returns></returns>
            public override Car CreateCar()
            {
                return new BenChiCar();
            }
        }

        static void Main(string[] args)
        {
            #region 工廠方法模式
            //初始化建立汽車的兩個工廠
            Factory hongQiCarFactory = new HongQiCarFactory();
            Factory aoDiCarFactory = new AoDiCarFactory();
            Factory benChiCarFactory = new BenChiCarFactory();

            //生產一輛紅旗汽車
            Car hongQi = hongQiCarFactory.CreateCar();
            hongQi.Go();

            //生產一輛奧迪汽車
            Car aoDi = aoDiCarFactory.CreateCar();
            aoDi.Go();

            //生產一輛奔馳汽車
            Car benChi = benChiCarFactory.CreateCar();
            benChi.Go();

            Console.Read();
            #endregion
        }
    }
View Code

    運行結果以下:

    3、Factory Method模式的幾個要點

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

    Factory Method模式經過面向對象的手法,將所要建立的具體對象工做延遲到子類,從而實現一種擴展(而非更改)的策略,較好地解決了這種緊耦

合關係;

    Factory Method模式解決「單個對象」的需求變化;

    AbstractFactory模式解決「系列對象」的需求變化;

    Builder模式解決「對象部分」的需求變化;

    3.一、工廠方法模式的優勢

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

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

    3.2工廠方法模式的缺點

    1)每次增長一個產品時,都須要增長一個具體類和對象實現工廠,使得系統中類的個數成倍增長,在必定程度上增長了系統的複雜度,同時也增長

了系統具體類的依賴,這並非什麼好事。

    3.3工廠方法模式的使用場合

    1)一個類不知道它所須要的對象的類。在工廠方法模式中,咱們不須要具體產品的類名,咱們只須要知道建立它的具體工廠便可。

    2)一個類經過其子類來指定建立那個對象。在工廠方法模式中,對於抽象工廠類只須要提供一個建立產品的接口,由其子類來肯定具體要建立的對

象。在程序運行時,子類對象將覆蓋父類對象,從而使得系統更容易擴展。

    3)將建立對象的任務委託給多個工廠子類中的某一個,客戶端在使用時能夠無須關心是哪個工廠子類建立產品子類,須要時再動態指定。

    4、.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"/>

    上面只摘選了部分配置文件,有時間你們能夠本身去研究一下。

    下面咱們具體看下工廠方法模式在Asp.net中是如何實現的?對一個Index.aspx頁面發出請求時,將會調用PageHandlerFactory中GetHandler方法來

建立一個Index.aspx對象,它們之間的類圖關係以下:

    5、總結

    每種模式都有本身的使用場合,切記,若是使用錯誤,還不如不用。工廠方法模式經過面向對象編程中的多態性來將對象的建立延遲到具體工廠中,

從而解決了簡單工廠模式中存在的問題,也很好地符合了開放封閉原則(即對擴展開發,對修改封閉)。

    學習設計模式咱們必定要謹記設計模式的幾大原則,不然是徒勞無功的。就像學務工同樣,咱們要記心法。幾大原則就像獨孤九劍的劍訣,學會了,

變化多端。

相關文章
相關標籤/搜索