關於抽象工廠模式的定義和實現

前言

大部分摘自:《設計模式之禪》 這本書

抽象工廠模式的定義

爲創建一組相關或相互 依賴的對象提供一個接口,而且無須指定它們的具體類。

一個好理解的例子:

講了女媧造人的故事。人是造出來了,世界也熱鬧了,可是低頭一看,都是清一色的類型,
缺少關愛、仇恨、喜怒哀樂等情緒,人類的生命太平淡了,女媧一想,猛然一拍腦袋,
忘記給人類定義性別了,那怎麼辦?抹掉重來,於是人類經過一次大洗禮,所有的人種都消滅掉了,世界又是空無一物,寂靜而又寂寞。

由於女媧之前的準備工作花費了非常大的精力,比如準備黃土、八卦爐等,從頭開始建立所有的事物也是不可能的,那就想在現有的條件下重新造人,儘可能舊物利用嘛。
人種(Produet產品類)應該怎麼改造呢?怎麼才能讓人類有愛有恨呢?是神仙當然有辦法了,定義互斥的性別,然後在每個個體中埋下一顆種子:異性相吸,成熟後就一定會去找個異性(這就是我們說的愛情原動力)。從設計角度來看,一個具體的對象通過兩個座標就可以確定:膚色和性別。

產品類分析完畢了,生產的工廠類(八卦爐)該怎麼改造呢?只有一個生產設備,要麼生產出來的全都是男性,要麼都是女性。那不行呀,這麼翻天覆地的改造就是爲了產生不同性別的人類。有辦法了!把目前已經有的生產設備八卦爐拆開,於是女媧就使用了“八卦複製術”,把原先的八卦爐一個變兩個,並且略加修改,就成了女性八卦爐(只生產女性人種)和男性八卦爐(只生產男性人種),於是乎女媧就開始準備生產了。

首先是人的抽象類:

  	public abstract class Human
    {
        public abstract void GetColor();
        public abstract void GetGender();

        public void Eat()
        {
            Console.WriteLine("吃飯咯!");
        }
    }

不同膚色人種的抽象類:

	public abstract class YellowHuman : Human
    {
        public override void GetColor()
        {
            Console.WriteLine("我是黃種人!");
        }
    }
	public abstract class WhiteHuman : Human
    {
        public override void GetColor()
        {
            Console.WriteLine("我是白種人!");
        }
    }

不同膚色不同性別的人類:

	public class FeMaleYellowHuman : YellowHuman
    {
        public override void GetGender()
        {
            Console.WriteLine("一名女性黃種人!");
        }
    }
    
    public class MaleYellowHuman : YellowHuman
    {
        public override void GetGender()
        {
            Console.WriteLine("一名男性黃種人!");
        }
    }

	public class FeMaleWhiteHuman : WhiteHuman
    {
        public override void GetGender()
        {
            Console.WriteLine("一名女性白種人!");
        }
    }
    
    public class MaleWhiteHuman : WhiteHuman
    {
        public override void GetGender()
        {
            Console.WriteLine("一名男性白種人!");
        }
    }

八卦爐的定義:

 	public interface IHumanFactory
    {
        public Human CreateWhiteHuman();

        public Human CreateYellowHuman();
    }

創建男性、女性的八卦爐:

 	public class MaleHumanFactory : IHumanFactory
    {
        public Human CreateWhiteHuman()
        {
            return new MaleWhiteHuman();
        }

        public Human CreateYellowHuman()
        {
            return new MaleYellowHuman();
        }
    }

	public class FeMaleHumanFactory : IHumanFactory
    {
        public Human CreateWhiteHuman()
        {
            return new FeMaleWhiteHuman();
        }

        public Human CreateYellowHuman()
        {
            return new FeMaleYellowHuman();
        }
    }

客戶端調用:

 class Program
    {
        static void Main(string[] args)
        {
            // 男性人類生成工廠
            IHumanFactory maleHumanFactory = new MaleHumanFactory();
            Human maleWhiteHuman = maleHumanFactory.CreateWhiteHuman();
            maleWhiteHuman.GetColor();
            maleWhiteHuman.GetGender();
            maleWhiteHuman.Eat();

            Human maleYellowHuman = maleHumanFactory.CreateYellowHuman();
            maleYellowHuman.GetColor();
            maleYellowHuman.GetGender();
            maleYellowHuman.Eat();

            // 女性人類生成工廠
            IHumanFactory feMaleHumanFactory = new FeMaleHumanFactory();
            Human feMaleWhiteHuman = feMaleHumanFactory.CreateYellowHuman();
            feMaleWhiteHuman.GetColor();
            feMaleWhiteHuman.GetGender();
            feMaleWhiteHuman.Eat();

            Human feMaleYellowHuman = feMaleHumanFactory.CreateYellowHuman();
            feMaleYellowHuman.GetColor();
            feMaleYellowHuman.GetGender();
            feMaleYellowHuman.Eat();
        }
    }

執行結果:
在這裏插入圖片描述

各種膚色的男性、女性都製造出來了,兩性之間產生了相互吸引力,於是情感產生,這個世界就多了-種小說的題材“愛情”。回頭來想想我們的設計,不知道大家有沒有去過工廠,每個工廠分很多車間,每個車間又分多條生產線,分別生產不同的產品,我們可以把八卦爐比喻爲車間,把八卦爐生產的工藝(生產白人、黑人還是黃人)稱爲生產線,如此來看就是一個女性生產車間,專門生產各種膚色的女性,一個是男性生產車間,專門生產各種膚色男性,生產完畢就可以在系統外組裝,什麼是組裝?嘿嘿,自己思考!
在這樣的設計下,各個車間和各條生產線的職責非常明確,在車間內各個生產出來的產品可以有耦合關係,你要知道世界上黑、黃、白人種的比例是:1:4:6, 那這就需要女媧娘娘在燒製的時候。就要做好比例分配,在一個車間內協調好。這就是抽象工廠模式。

抽象工廠模式的通用類圖

在這裏插入圖片描述

抽象工廠模式的優缺點

優點:

  • 良好的封裝性,每個產品的實現類不是高層模塊要關心的,它要關心的是什麼?是接口,是抽象,它不關心對象是如何創建出來(如上面通用類圖),這由誰負責呢?工廠類,只要知道工廠類是誰,我就能創建出一個需要的對象,省時省力,優秀設計就應該如此。
  • 產品族內的約束爲非公開狀態。例如生產男女比例的問題上,猜想女媧娘娘肯定有自己的打算,不能讓女盛男衰,否則女性的優點不就體現不出來了嗎?那在抽象工廠模式,就應該有這樣的一個約束:每生產1個女性,就同時生產出1.2個男性,這樣的生產過程對調用工廠類的高層模塊來說是透明的,它不需要知道這個約束,我就是要一個黃色女性產品就可以了,具體的產品族內的約束是在工廠內實現的。

缺點:

抽象工廠模式的最大缺點就是產品族擴展非常困難,爲什麼這麼說呢?我們以通用代碼爲例,如果要增加一個產品C,也就是說產品家族由原來的2個增加到3個,看看我們的程序有多大改動吧!
抽象類AbstractCreator要增加一個方法createProductC(),,然後兩個實現類都要修改,想想看,這嚴重違反了開閉原則,而且我們一直說明抽象類和接口是一個契約。 改變契約,所有與契約有關係的代碼都要修改,那麼這段代碼叫什麼?叫“有毒代碼”,只要與這段代碼有關係,就可能產生侵害的危險!

抽象工廠模式的使用場景

抽象工廠模式的使用場景定義非常簡單:一個對象族(或是一組沒有任何關係的對象)都有相同的約束,則可以使用抽象工廠模式。什麼意思呢?例如一個文本編輯器和一個圖片處理器,都是軟件實體,但是linux下的文本編輯器和Windows下的文本編輯器雖然功能和界面都相同,但是代碼實現是不同的,圖片處理器也有類似情況。也就是具有了共同的約束條件:操作系統類型。於是我們可以使用抽象工廠模式,產生不同操作系統下的編輯器和圖片處理器。

一個模式在什麼情況下才能夠使用,是很多讀者比較困惑的地方。抽象工廠模式是一個簡單的模式,使用的場景非常多,大家在軟件產品開發過程中,涉及不同操作系統的時候,都可以考慮使用抽象工廠模式。
例如一個應用,需要在三個不同平臺(Windows、 Linux、 Android (Google發佈的智能終端操作系統) )上運行,你會怎麼設計?分別設計三套不同的應用?非也,通過抽象工廠模式屏蔽掉操作系統對應用的影響。三個不同操作系統上的軟件功能、應用邏輯、UI都應該是非常類似的,唯一不同的是調用不同的工廠方法,由不同的產品類去處理與操作系統交互的信息。

使用抽象工廠模式的注意事項

在抽象工廠模式的缺點中,我們提到抽象工廠模式的產品族擴展比較困難,但是一定要清楚,是產品族擴展困難,而不是產品等級。在該模式下,產品等級是非常容易擴展的,增加一個產品等級,只要增加一個工廠類負責新增加出來的產品生產任務即可。也就是說橫向擴展容易,縱向擴展困難。
以人類爲例子,產品等級中只有男、女兩個性別,現實世界還有一種性別:雙性人,既是男人也是女人(俗語就是陰陽人),那我們要擴展這個產品等級也是非常容易的,增加三個產品類,分別對應不同的膚色,然後再創建一個工廠
類,專門負責不同膚色人的雙性,人的創建任務,完全通過擴展來實現需求的變更,從這一點上看,抽象工廠模式是符合開閉原則的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章