設計模式(三)抽象工廠方法模式

thekingisalwayslucky發表於2019-04-18

思路:

在工廠模式,如果有多個手機品牌供選擇,當我們再新增新的手機品牌的時候,用簡單工廠模式,我們就不得不修改簡單工廠類,不滿足開放封閉原則。於是就引出了工廠方法模式。

那麼問題又來了,如果我們之前提到的全是3G手機,現在市場上又出來了4G手機,那麼同樣的品牌可能既有3G手機又有4G手機,我們又應當怎樣去設計這些類的結構呢?

我們其實只需要對工廠方法模式中的工廠類進行簡單的修改就可以滿足這個條件了。

首先我們可以將手機工廠類轉變成介面,提供建立某品牌3G手機的方法和建立某品牌4G手機的方法,這些方法只宣告不實現。具體的實現交給對應品牌的工廠類去實現。由對應品牌的工廠類去完成建立該品牌的3G手機或者該品牌的4G手機。

  class Program
    {
        static void Main(string[] args)
        {
            Factory f = new AppleFactory(); // AppleFactory

            MobilePhone3G ph3g = f.CreatePhone3G();
            ph3g.Call();
            ph3g.SendMSG();

            MobilePhone4G ph4g = f.CreatePhone4G();
            ph4g.Call();
            ph4g.SendMSG();

            Console.ReadKey();
        }
    }

    abstract class Factory
    {
        public abstract MobilePhone3G CreatePhone3G();
        public abstract MobilePhone4G CreatePhone4G();
    }

    class AppleFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new Iphone4S();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new Iphone6();
        }
    }
    class SamsungFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new GalaxyNote2();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new GalaxyNote4();
        }
    }
    class HTCFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new HTCOneM7();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new HTCOneM8();
        }
    }
    class MicrosoftFactory : Factory
    {
        public override MobilePhone3G CreatePhone3G()
        {
            return new Lumia820();
        }
        public override MobilePhone4G CreatePhone4G()
        {
            return new Lumia920();
        }
    }
    abstract class MobilePhone3G
    {
        public abstract void Call();
        public abstract void SendMSG();
    }


    class Iphone4S : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用Iphone4S打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Iphone4S發簡訊");
        }
    }

    class GalaxyNote2 : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用GalaxyNote2打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用GalaxyNote2發簡訊");
        }
    }

    class HTCOneM7 : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用HTCOneM7打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用HTCOneM7發簡訊");
        }
    }

    class Lumia820 : MobilePhone3G
    {
        public override void Call()
        {
            Console.WriteLine("用Lumia820打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Lumia820發簡訊");
        }
    }

    abstract class MobilePhone4G
    {
        public abstract void Call();
        public abstract void SendMSG();
    }


    class Iphone6 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用Iphone6打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Iphone6發簡訊");
        }
    }

    class GalaxyNote4 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用GalaxyNote4打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用GalaxyNote4發簡訊");
        }
    }

    class HTCOneM8 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用HTCOneM8打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用HTCOneM8發簡訊");
        }
    }

    class Lumia920 : MobilePhone4G
    {
        public override void Call()
        {
            Console.WriteLine("用Lumia920打電話");
        }
        public override void SendMSG()
        {
            Console.WriteLine("用Lumia920發簡訊");
        }
    }
複製程式碼

這樣,就算我們要新增一類新的手機品牌,也能夠從容應對了。

UML圖:

設計模式(三)抽象工廠方法模式

吐槽:

抽象工廠模式(Abstract Factory Pattern):提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。

該模式的優點:

抽象工廠模式的主要優點是隔離了具體類的生成,使得客戶並不需要知道什麼被建立。由於這種隔離,更換一個具體工廠就變得相對容易。

所有的具體工廠都實現了抽象工廠中定義的那些公共介面,因此只需改變具體工廠的例項,就可以在某種程度上改變整個軟體系統的行為。另外,應用抽象工廠模式可以實現高內聚低耦合的設計目的,因此抽象工廠模式得到了廣泛的應用。

該模式的缺點:

抽象工廠模式的缺點是在新增新的產品物件時,難以擴充套件抽象工廠以便生產新種類的產品,這是因為在抽象工廠角色中規定了所有可能被建立的產品集合,要支援新種類的產品就意味著要對該介面進行擴充套件,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來很多不便。

開閉原則的傾斜性(增加新的工廠和產品族容易,增加新的產品等級結構麻煩)

使用情景:

一個系統不應當依賴於產品類例項如何被建立、組合和表達的細節,這對於所有形態的工廠模式都很重要。 系統有多於一個的產品族,而客戶端只消費其中某一產品族。 系統提供一個產品類的庫,所有的產品以同樣的介面出現,從而使客戶端不依賴於實現。

note:一個程式設計師如果從來沒有熬夜寫程式的經歷,不能算是一個好程式設計師。因為他沒有痴迷過,所以不會有大成就。

相關文章