第8章 工廠方法模式
8.1 女媧造人的故事
東漢《風俗通》記錄了一則神話故事:“開天辟地,未有人民,女媧搏黃土做人”,講述的內容就是大家非常熟悉的女媧造人的故事。開天辟地之初,大地上并沒有生物,只有蒼茫大地,純粹而潔凈的自然環境,寂靜而又寂寞,于是女媧決定創造一個新物種(即人類)來增加世界的繁榮,怎么制造呢?
別忘了女媧是神仙,沒有辦不到的事情,造人的過程是這樣的:首先,女媧采集黃土捏成人的形狀,然后放到八卦爐中燒制,最后放置到大地上生長,工藝過程是沒有錯的,但是意外隨時都會發生:
第一次烤泥人,感覺應該熟了,往大地上一放,哇,沒烤熟!于是一個白人誕生了!(這也是缺乏經驗的最好證明。)
第二次烤泥人,上一次沒烤熟,這次多烤一會兒,放到世間一看,嘿,熟過頭了,于是黑人誕生了!
第三次烤泥人,一邊燒制一邊察看,直到表皮微黃,嘿,剛剛好,于是黃色人種出現了!
這個造人過程是比較有意思的,是不是可以通過軟件開發來實現這個過程呢?古人云:“三人行,必有我師焉”,在面向對象的思維中,萬物皆對象,是對象我們就可以通過軟件設計來實現。首先對造人過程進行分析,該過程涉及三個對象:女媧、八卦爐、三種不同膚色的人。女媧可以使用場景類Client來表示,八卦爐類似于一個工廠,負責制造生產產品(即人類),三種不同膚色的人,他們都是同一個接口下的不同實現類,都是人嘛,只是膚色、語言不同,對于八卦爐來說都是它生產出的產品。分析完畢,我們就可以畫出如圖8-1所示的類圖。
類圖比較簡單,AbstractHumanFactory是一個抽象類,定義了一個八卦爐具有的整體功能,HumanFactory為實現類,完成具體的任務——創建人類;Human接口是人類的總稱,其三個實現類分別為三類人種;NvWa類是一個場景類,負責模擬這個場景,執行相關的任務。
我們定義的每個人種都有兩個方法:getColor(獲得人的皮膚顏色)和talk(交談),其源代碼如代碼清單8-1所示。

圖8-1 女媧造人類圖
代碼清單8-1 人類總稱
public?interface?Human?{
?????//每個人種的皮膚都有相應的顏色
?????public?void?getColor();
?????//人類會說話
?????public?void?talk();
}
接口Human是對人類的總稱,每個人種都至少具有兩個方法,黑色人種、黃色人種、白色人種的代碼分別如代碼清單8-2、代碼清單8-3、代碼清單8-4所示。
代碼清單8-2 黑色人種
public?class?BlackHuman?implements?Human?{
?????public?void?getColor(){
?????????????System.out.println("黑色人種的皮膚顏色是黑色的!");
?????}
?????public?void?talk()?{
?????????????System.out.println("黑人會說話,一般人聽不懂。");
?????}
}
代碼清單8-3 黃色人種
public?class?YellowHuman?implements?Human?{
?????public?void?getColor(){
?????????????System.out.println("黃色人種的皮膚顏色是黃色的!");
?????}
?????public?void?talk()?{
?????????????System.out.println("黃色人種會說話,一般說的都是雙字節。");
?????}
}
代碼清單8-4 白色人種
public?class?WhiteHuman?implements?Human?{
?????public?void?getColor(){
?????????????System.out.println("白色人種的皮膚顏色是白色的!");
?????}
?????public?void?talk()?{
?????????????System.out.println("白色人種會說話,一般都是但是單字節。");
?????}
}
所有的人種定義完畢,下一步就是定義一個八卦爐,然后燒制人類。我們想象一下,女媧最可能給八卦爐下達什么樣的生產命令呢?應該是“給我生產出一個黃色人種(YellowHuman類)”,而不會是“給我生產一個會走、會跑、會說話、皮膚是黃色的人種”,因為這樣的命令增加了交流的成本,作為一個生產的管理者,只要知道生產什么就可以了,而不需要事物的具體信息。通過分析,我們發現八卦爐生產人類的方法輸入參數類型應該是Human接口的實現類,這也解釋了為什么類圖上的AbstractHumanFactory抽象類中createHuman方法的參數為Class類型。其源代碼如代碼清單8-5所示。
代碼清單8-5 抽象人類創建工廠
public?abstract?class?AbstractHumanFactory?{
?????public?abstract?<T?extends?Human>?T?createHuman(Class<T>?c);
}
注意,我們在這里采用了泛型(Generic),通過定義泛型對createHuman的輸入參數產生兩層限制:
● 必須是Class類型;
● 必須是Human的實現類。
其中的"T"表示的是,只要實現了Human接口的類都可以作為參數,泛型是JDK 1.5中的一個非常重要的新特性,它減少了對象間的轉換,約束其輸入參數類型,對Collection集合下的實現類都可以定義泛型。有關泛型的詳細知識,請參考相關的Java語法文檔。
目前女媧只有一個八卦爐,其實現生產人類的方法,如代碼清單8-6所示。
代碼清單8-6 人類創建工廠
public?class?HumanFactory?extends?AbstractHumanFactory?{
?????public?<T?extends?Human>?T?createHuman(Class<T>?c){
?????????????//定義一個生產的人種
?????????????Human?human=null;
?????????????try?{
??????????????????????//產生一個人種
??????????????????????human?=?(T)Class.forName(c.getName()).newInstance();
?????????????}?catch?(Exception?e)?{
??????????????????System.out.println("人種生成錯誤!");
?????????????}
?????????????return?(T)human;
?????}
}
人種有了,八卦爐也有了,剩下的工作就是女媧采集黃土,然后命令八卦爐開始生產,其過程如代碼清單8-7所示。
代碼清單8-7 女媧類
public?class?NvWa?{
?????public?static?void?main(String[]?args)?{
?????????????//聲明陰陽八卦爐
?????????????AbstractHumanFactory?YinYangLu?=?new?HumanFactory();???????????????
?????????????//女媧第一次造人,火候不足,于是白人產生了
?????????????System.out.println("--造出的第一批人是白色人種--");
?????????????Human?whiteHuman?=?YinYangLu.createHuman(WhiteHuman.class);
?????????????whiteHuman.getColor();
?????????????whiteHuman.talk();?????????
?????????????//女媧第二次造人,火候過足,于是黑人產生了
?????????????System.out.println("\n--造出的第二批人是黑色人種--");
?????????????Human?blackHuman?=?YinYangLu.createHuman(BlackHuman.class);
?????????????blackHuman.getColor();
?????????????blackHuman.talk();?????????
?????????????//第三次造人,火候剛剛好,于是黃色人種產生了
?????????????System.out.println("\n--造出的第三批人是黃色人種--");
?????????????Human?yellowHuman?=?YinYangLu.createHuman(YellowHuman.class);
?????????????yellowHuman.getColor();
?????????????yellowHuman.talk();
?????}
}
人種有了,八卦爐有了,負責生產的女媧也有了,激動人心的時刻到來了,我們運行一下,結果如下所示。
--造出的第一批人是白色人種--
白色人種的皮膚顏色是白色的!
白色人種會說話,一般都是單字節。
--造出的第二批人是黑色人種--
黑色人種的皮膚顏色是黑色的!
黑人會說話,一般人聽不懂。
--造出的第三批人是黃色人種--
黃色人種的皮膚顏色是黃色的!
黃色人種會說話,一般說的都是雙字節。
哇,人類的生產過程就展現出來了!這個世界就熱鬧起來了,黑人、白人、黃人都開始活動了,這也正是我們現在的真實世界。以上就是工廠方法模式(沒錯,對該部分有疑問,請繼續閱讀下去)。
- 前言
- 第一部分 大旗不揮,誰敢沖鋒——6大設計原則全新解讀
- 第1章 單一職責原則
- 1.2 絕殺技,打破你的傳統思維
- 1.3 我單純,所以我快樂
- 1.4 最佳實踐
- 第2章 里氏替換原則
- 2.2 糾紛不斷,規則壓制
- 2.3 最佳實踐
- 第3章 依賴倒置原則
- 3.2 言而無信,你太需要契約
- 3.3 依賴的三種寫法
- 3.4 最佳實踐
- 第4章 接口隔離原則
- 4.2 美女何其多,觀點各不同
- 4.3 保證接口的純潔性
- 4.4 最佳實踐
- 第5章 迪米特法則
- 5.2 我的知識你知道得越少越好
- 5.3 最佳實踐
- 第6章 開閉原則
- 6.2 開閉原則的廬山真面目
- 6.3 為什么要采用開閉原則
- 6.4 如何使用開閉原則
- 6.5 最佳實踐
- 第二部分 真刀實槍 ——23種設計模式完美演繹
- 第7章 單例模式
- 7.2 單例模式的定義
- 7.3 單例模式的應用
- 7.4 單例模式的擴展
- 7.5 最佳實踐
- 第8章 工廠方法模式
- 8.2 工廠方法模式的定義
- 8.3 工廠方法模式的應用
- 8.4 工廠方法模式的擴展
- 8.5 最佳實踐
- 第9章 抽象工廠模式
- 9.2 抽象工廠模式的定義
- 9.3 抽象工廠模式的應用
- 9.4 最佳實踐
- 第10章 模板方法模式
- 10.2 模板方法模式的定義
- 10.3 模板方法模式的應用
- 10.4 模板方法模式的擴展
- 10.5 最佳實踐
- 第11章 建造者模式
- 11.2 建造者模式的定義
- 11.3 建造者模式的應用
- 11.4 建造者模式的擴展
- 11.5 最佳實踐
- 第12章 代理模式
- 12.2 代理模式的定義
- 12.3 代理模式的應用
- 12.4 代理模式的擴展
- 12.5 最佳實踐
- 第13章 原型模式
- 13.2 原型模式的定義
- 13.3 原型模式的應用
- 13.4 原型模式的注意事項
- 13.5 最佳實踐
- 第14章 中介者模式
- 14.2 中介者模式的定義
- 14.3 中介者模式的應用
- 14.4 中介者模式的實際應用
- 14.5 最佳實踐
- 第15章 命令模式
- 15.2 命令模式的定義
- 15.3 命令模式的應用
- 15.4 命令模式的擴展
- 15.5 最佳實踐
- 第16章 責任鏈模式
- 16.2 責任鏈模式的定義
- 16.3 責任鏈模式的應用
- 16.4 最佳實踐
- 第17章 裝飾模式
- 17.2 裝飾模式的定義
- 17.3 裝飾模式應用
- 17.4 最佳實踐
- 第18章 策略模式
- 18.2 策略模式的定義
- 18.3 策略模式的應用
- 18.4 策略模式的擴展
- 18.5 最佳實踐
- 第19章 適配器模式
- 19.2 適配器模式的定義
- 19.3 適配器模式的應用
- 19.4 適配器模式的擴展
- 19.5 最佳實踐
- 第20章 迭代器模式
- 20.2 迭代器模式的定義
- 20.3 迭代器模式的應用
- 20.4 最佳實踐
- 第21章 組合模式
- 21.2 組合模式的定義
- 21.3 組合模式的應用
- 21.4 組合模式的擴展
- 21.5 最佳實踐
- 第22章 觀察者模式
- 22.2 觀察者模式的定義
- 22.3 觀察者模式的應用
- 22.4 觀察者模式的擴展
- 22.5 最佳實踐
- 第23章 門面模式
- 23.2 門面模式的定義
- 23.3 門面模式的應用
- 23.4 門面模式的注意事項
- 23.5 最佳實踐
- 第24章 備忘錄模式
- 24.2 備忘錄模式的定義
- 24.3 備忘錄模式的應用
- 24.4 備忘錄模式的擴展
- 24.5 最佳實踐
- 第25章 訪問者模式
- 25.2 訪問者模式的定義
- 25.3 訪問者模式的應用
- 25.4 訪問者模式的擴展
- 25.5 最佳實踐
- 第26章 狀態模式
- 26.2 狀態模式的定義
- 26.3 狀態模式的應用
- 第27章 解釋器模式
- 27.2 解釋器模式的定義
- 27.3 解釋器模式的應用
- 27.4 最佳實踐
- 第28章 享元模式
- 28.2 享元模式的定義
- 28.3 享元模式的應用
- 28.4 享元模式的擴展
- 28.5 最佳實踐
- 第29章 橋梁模式
- 29.2 橋梁模式的定義
- 29.3 橋梁模式的應用
- 29.4 最佳實踐
- 第三部分 誰的地盤誰做主 ——設計模式PK
- 第30章 創建類模式大PK
- 30.1 工廠方法模式VS建造者模式
- 30.2 抽象工廠模式VS建造者模式
- 第31章 結構類模式大PK
- 31.1 代理模式VS裝飾模式
- 31.2 裝飾模式VS適配器模式
- 第32章 行為類模式大PK
- 32.1 命令模式VS策略模式
- 32.2 策略模式VS狀態模式
- 32.3 觀察者模式VS責任鏈模式
- 第33章 跨戰區PK
- 33.1 策略模式VS橋梁模式
- 33.2 門面模式VS中介者模式
- 33.3 包裝模式群PK
- 第四部分 完美世界 ——設計模式混編
- 第34章 命令模式+責任鏈模式
- 34.2 混編小結
- 第35章 工廠方法模式+策略模式
- 35.2 混編小結
- 第36章 觀察者模式+中介者模式
- 36.2 混編小結
- 第五部分 擴展篇
- 第37章 MVC框架
- 37.2 最佳實踐
- 第38章 新模式
- 38.1 規格模式
- 38.2 對象池模式
- 38.3 雇工模式
- 38.4 黑板模式
- 38.5 空對象模式
- 附錄 23種設計模式彩圖