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

前言

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

工廠模式的定義:

定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使-一個 類的實例化延遲到其子類。

一個好理解的例子:

東漢《風俗通》記錄了一則神話故事, 開天闢地,未有人民,女媧搏黃土做人”,講述的內容就是大家非常熟悉的女媧造人的故事。開天闢地之初,大地上並沒有生物,只有蒼茫大地,純粹而潔淨的自然環境,寂靜而又寂寞, 於是女娟決定創造一個新物種(即人類)來增加世界的繁榮,怎麼製造呢?
別忘了 女媧是神仙,沒有辦不到的事情,造人的過程是這樣的,首先,女媧採集黃土捏成人的形狀,然後放到八卦爐中燒製,最後放置到大地上生長,工藝過程是沒有錯的,但是意外隨時都會發生。
第一次烤泥人,感覺應該熟了,往大地上一放,哇沒烤熟!於是一個白人誕生了!
第二次烤泥人,上一次沒烤熟,這次多烤一會兒, 放到世間一看,嘿,熟過頭了,於是黑人誕生了!
第三次烤泥人,邊燒製一邊察看,直到表皮微責,嘿,剛好,於是黃色人種出現了!

這個造人過程是比較有意思的,是不是可以通過代碼來實現這個過程呢?
在面向對象的思維中,萬物皆對象,是對象我們就可以通過軟件設計來實現。

  1. 首先對造人過程進行分析,該過程步及三個對象:女媧、八卦爐、三種不同膚色的人。
  2. 女媧可以使用場景類Client來表示。
  3. 八卦爐類似於一個工廠,負責製造產品(即人類)。
  4. 三種不同膚色的人,他們都是同一個抽象類(人類)下的不同實現,都是人類,只是膚色、語言不同。對於八卦爐來說都是它生產出的產品。

先定義工廠接口:

    public interface IFactory
    {
        public T CreateHuman<T>() where T : Human;
    }

定義工廠的實現類:

	public class HumanFactory: IFactory
    {
        public T CreateHuman<T>() where T : Human
        {
            // 動態實例化泛型類
            return Activator.CreateInstance<T>();
        }
    }

定義人的抽象類:

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

定義不同膚色的人類:

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

	public class BlackHuman : Human
    {
        public override void GetColor()
        {
            Console.WriteLine("我是黑人!");
        }
    }

客戶端:

	class Program
    {
        static void Main(string[] args)
        {
			// 實例化工廠類
            HumanFactory factory = new HumanFactory();
 
            Human yellowHuman = factory.CreateHuman<YellowHuman>();
            yellowHuman.GetColor();

            Human whiteHuman = factory.CreateHuman<WhiteHuman>();
            whiteHuman.GetColor();
            
            Human blackHuman = factory.CreateHuman<BlackHuman>();
            whiteHuman.GetColor();
        }
    }

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

工廠模式的優點呢?我們爲什麼要使用工廠模式?

首先,良好的封裝性代碼結構清晰。一個對象創建是有條件約束的,如一個調用者需要一個具體的產品對象。只要知道這個產品的類名即可,不用知道創建對象的艱辛過程,降低模塊間的耦合。

其次,工廠模式的擴展性非常優秀。在增加產品類的情況下,只要適當地修改具體的工廠類或擴展一個工廠類。就可以完成 擁抱變化。例如在我們的例子中,需要增加一個棕色人種,則只需要增加一個BrownHuman類 ,工廠類不需要任何修改就可完成系統擴展。

再次,屏蔽產品類。這一特點非常重要,產品類的實現如何變化,調用者都不需要關心,它只需要關心產品的接口,只要接口保持不變,系統中的上層模塊就不要發生變化。因爲產品類的實例化工作是由工廠類負責的,一個產品對象具體由哪一個產品生成是由工廠類決定的。

在數據庫開發中,大家應該能夠深刻體會到工廠方法模式的好處:如果使用JDBC連接數據庫,數據庫從MySQL切換到Oracle,需要改動的地方就是切換一下驅動名稱(前提條件是SQL語句是標準語句),其他的都不需要修改,這是工廠方法模式靈活性的一個直接案例。

最後,工廠方法模式是典型的解耦框架。高層模塊值需要知道產品的抽象 類,其他的實現類都不用關心,符合迪米特法則,我不需要的就不要去交流;也符合依賴倒置原則,只依賴產品類的抽象;當然也符合里氏替換原則,使用產品子類替換產品父類,沒問題!

工廠模式的適用場景

首先,工廠方法模式是new一個對象的替代品,所以在所有需要生成對象的地方都可以使用,但是需要慎重地考慮是否要增加一個工廠類進行管理,增加代碼的複雜度。

其次,需要靈活的、可擴展的框架時,可以考慮採用工廠方法模式。萬物皆對象,那萬物也就皆產品類。
例如需要設計一個連接郵件服務器的框架,有三種網絡協議可供選擇: POP3、 IMAP、HTTP,我們就可以把這三種連接方法作爲產品類,定義一個接口如IConnectMail, 然後定義對郵件的操作方法,用不同的方法實現三個具體的產品類(也就是連接方式)。再定義一個工廠方法,按照不同的傳入條件,選擇不同的連接方式。如此設計,可以做到完美的擴展。

簡單工廠模式

我們這樣考慮一個問題: 一個模塊僅需要一個工廠類,沒有必要把它生產出來,使用靜態的方法就可以了,根據這一要求, 我們把上例中的HumanFactory修改一下,把生產Human的方法改成靜態的,並且去掉IFactory接口就行了。
工廠類:

	 public class HumanFactory
    {
        public static T CreateHuman<T>() where T : Human
        {
            return Activator.CreateInstance<T>();
        }
    }

客戶端:

 class Program
    {
        static void Main(string[] args)
        {

            //HumanFactory factory = new HumanFactory();

            Human yellowHuman = HumanFactory.CreateHuman<YellowHuman>();
            yellowHuman.GetColor();

            Human whiteHuman = HumanFactory.CreateHuman<WhiteHuman>();
            whiteHuman.GetColor();

            Human blackHuman = HumanFactory.CreateHuman<BlackHuman>();
            blackHuman.GetColor();
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章