抽象工厂模式的详解
1.為什么需要抽象工廠模式?
雖然工廠方法模式引入工廠等級結構,解決了簡單工廠模式中工廠類職責過重的問題,但由于工廠方法模式中每個工廠只創建一類具體類的對象,如果需要的具體類很多時候,這將會導致系統當中的工廠類過多,這勢必會增加系統的開銷。此時,我們可以考慮將一些相關的具體類組成一個“具體類族”,由同一個工廠來統一生產,這就是我們需要抽象工廠模式的原因。
2.抽象工廠模式的定義
抽象工廠模式:
是一種為用戶類提供一個創建一組相關或相互依賴的對象的接口,而且用戶類無需指定他們的具體類就能得到同族的不同等級的產品的模式結構。
那什么是同族,什么是同等級的產品呢?
下圖所示戴爾工廠A和 惠普工廠B所生產的鍵盤與鼠標對應的關系圖。
通過上面這張圖對剛才的定義通俗的說:在用戶類中,創建了指定具體的工廠類后,在使用時就無需再關心如何對它們進行實例化的細節,也無需知道它實現了那些方法,用戶類只需要跟抽象的IFactory接口打交道,調用接口的方法就能獲得需要的產品,這種的工廠模式稱為抽象工廠模式。
3.抽象工廠模式的結構和實現
抽象工廠模式同工廠方法模式一樣,也是由抽象工廠、具體工廠、抽象產品和具體產品等 4 個要素構成,但抽象工廠中方法個數不同,抽象產品的個數也不同。現在我們來分析其基本結構和實現方法。
①. 模式的結構
抽象工廠模式的主要角色如下:
抽象工廠(Abstract Factory):提供了創建產品的接口,它包含多個創建產品的方法 newProduct(),可以創建多個不同等級的產品。
具體工廠(Concrete Factory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的創建。
抽象產品(Product):定義了產品的規范,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品。
具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來創建,它同具體工廠之間是多對一的關系。
下面來看一下抽象工廠模式結構的抽象uml類圖
從上圖 可以看出抽象工廠模式的結構同工廠方法模式的結構相似,但不同的是抽象工廠模式的每個工廠類不僅生產多種不同具體產品,而且創建產品的方法也不止一個。
②. 抽象工廠模式的應用實例
由于工廠方法模式每個工廠類只能生產一種具體產品,比如戴爾工廠類,它只能生產戴爾鼠標這一種產品類;現在我們想要戴爾工廠不僅生產戴爾鼠標,而且生產戴爾鍵盤,又需要惠普工廠不僅生產惠普鼠標,而且生產惠普鍵盤。
下面我們來看一下該例子的uml類圖:
③.該例子抽象生產模式實現的代碼
①創建鼠標類的共同接口 //鼠標的接口 interface mouse {public void show(); }②創建戴爾鼠標類實現鼠標接口,即具體的產品類 //具體的產品類(戴爾鼠標),來實現鼠標這個抽象接口 class Dellmouse implements mouse {public void show() {System.out.println("這是個戴爾鼠標");} }③創建惠普鼠標類來實現鼠標接口,即具體的產品類 //具體的產品類(惠普鼠標),來實現鼠標這個抽象接口 class Hpmouse implements mouse {public void show() {System.out.println("這是個惠普鼠標");} }④創建鍵盤類的共同接口 //鍵盤的接口 interface keyboard {public void show(); }⑤創建戴爾鍵盤類來實現鍵盤接口,即具體的產品類 //具體的產品類(戴爾鍵盤),來實現鍵盤這個抽象接口 class Dellkeyboard implements keyboard {public void show() {System.out.println("這是個戴爾鍵盤");} }⑥創建惠普鍵盤類來實現鍵盤接口,即具體的產品類 //具體的產品類(惠普鍵盤),來實現鍵盤這個抽象接口 class Hpkeyboard implements keyboard {public void show() {System.out.println("這是個惠普鍵盤");} }⑦創建抽象工廠類共同接口 //抽象工廠類接口 interface PCFactory {public mouse createmouse();public keyboard createkeyb(); }⑧創建具體工廠類A,來實現抽象工廠類接口 //具體工廠類A,來實現抽象工廠類接口class FactoryA implements PCFactory {public mouse createmouse() { //實現接口的方法return new Dellmouse(); //返回創建具體產品類1}public keyboard createkeyb() { //實現接口的方法return new Dellkeyboard(); //返回創建具體產品類2} }⑨創建具體工廠類B,來實現抽象工廠類接口 //具體工廠類B,來實現抽象工廠類接口 class FactoryB implements PCFactory {public mouse createmouse() { //實現抽象接口方法return new Hpmouse(); //返回創建具體類}public keyboard createkeyb() { //實現抽象接口方法return new Hpkeyboard(); //返回創建具體類} }⑩用戶端的調用 //用戶端的調用 public class user {public static void main(String[] args) {PCFactory f=new FactoryA(); f.createmouse().show(); //用戶類只跟接口打交道,只需調用接口的方法f.createkeyb().show();PCFactory ff=new FactoryB();ff.createmouse().show();ff.createkeyb().show();} }運行結果:
4.應用場景
抽象工廠模式通常適用于以下場景:
①當用戶端需要創建的對象是一系列相互關聯或相互依賴的產品族時,抽象工廠模式很適合應用這種情況。(比如說現在已經有一個工廠在生產產品,但是現在用戶端想要創建另一個工廠也要生產同樣的產品,這種情況抽象工廠模式就很適合)
②當系統中有多個產品族,但用戶端每次只需要其中的某一族產品時,抽象工廠模式也非常適合這種情況。(比如說有的人只喜歡某一品牌的衣服和鞋子,這種情況抽象工廠模式也很適合)
③當系統中提供了產品的類庫,且所有產品的接口相同時,要求客戶端類不依賴產品實例的創建細節和內部結構時,抽象工廠也適合這種情況。
5.優缺點
優點
①抽象工廠模式隔離了具體產品/類的生成, 使得客戶并不需要知道什么被創建。 由于這種隔離,更換或增加一個具體工廠就變得相對容易, 所有的具體工廠都實現了抽象工廠中定義的那些公共接口, 因此只需改變具體工廠的實例, 就可以在某種程度上改變整個軟件系統的行為。
②當一個族中的多個對象被設計成一起工作時, 它能夠保證客戶端始終只使用同一個族中的對象。
③增加新的族很方便, 無須修改已有系統, 符合“開閉原則”。
缺點:
增加新的等級結構麻煩, 需要對原有系統進行較大的修改, 甚至需要修改抽象層代碼,這顯然會帶來較大的不便, 違背了“開閉原則”。
6.總結:
抽象工廠模式是為用戶端 提供一個創建一系列相關或相互依賴對象的接口,用戶端無需知道他們需要的產品怎么做的,它只需要調用接口方法就行。
抽象工廠模式,不僅可以實現多個接口,而且每個工廠也可以生產多種產品類,和工廠方法模式一樣,抽象工廠模式同樣實現了開發封閉原則。
注意:當抽象工廠模式中的每個工廠類都只生產一種具體的產品時,這時候的抽象工廠模式相當于工廠方法模式。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: 整数划分递归相关问题
- 下一篇: 进程的解析