设计模式解密(2)- 工厂模式(简单工厂、工厂方法、抽象工厂)
?
1、前言
工廠模式主要是為創(chuàng)建對象提供接口,將創(chuàng)建對象的過程隔離起來,實現(xiàn)了創(chuàng)建者與調(diào)用者的分離,提高了程序的靈活性;
核心本質(zhì):
實例化對象,用工廠方法代替new操作;
將選擇實現(xiàn)類、創(chuàng)建對象統(tǒng)一管理和控制,從而將調(diào)用者跟我們實現(xiàn)類解耦;
工廠模式分類:
簡單工廠模式(Simple Factory)(又稱:靜態(tài)工廠方法模式)
工廠方法模式(Factory Method)
抽象工廠模式(Abstract Factory)
GOF在《設計模式》一書中將工廠模式分為兩類:工廠方法模式(Factory Method)與抽象工廠模式(Abstract Factory),將簡單工廠模式(Simple Factory)看為工廠方法模式的一種特例,兩者歸為一類;
?類型:創(chuàng)建型模式
2、簡單工廠模式
2-1、介紹
簡單工廠模式又被稱為靜態(tài)工廠方法模式;
簡單工廠模式是由一個工廠(注意是一個!)對象決定創(chuàng)建出哪一種產(chǎn)品類的實例;
實現(xiàn)方式的實質(zhì):由一個工廠類根據(jù)傳入的參數(shù),動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類(這些產(chǎn)品類繼承自一個父類或接口)的實例;
現(xiàn)實生活中,工廠是負責生產(chǎn)產(chǎn)品的;同樣在設計模式中,簡單工廠模式我們可以理解為負責生產(chǎn)對象的一個類,稱為“工廠類”;
?? ?英文:Simple Factory
2-2、解決的問題
將“類實例化的操作”與“使用對象的操作”分開,讓使用者不用知道具體參數(shù)就可以實例化出所需要的“產(chǎn)品”類,從而避免了在客戶端代碼中顯式指定,實現(xiàn)了解耦;
即使用者可直接消費產(chǎn)品而不需要知道其生產(chǎn)的細節(jié);
2-3、實例引入
背景:這有一個手機生產(chǎn)工廠,能生產(chǎn)多種手機
先定義一個抽象手機類:
package com.designmode.factory.simple; /** * 類說明 :抽象手機類 */ public abstract class Mobile {}定義具體的手機:小米手機
package com.designmode.factory.simple; /** * 類說明 :具體手機--小米手機 */ public class XiaomiMobile extends Mobile{}定義具體的手機:華為手機
package com.designmode.factory.simple; /** * 類說明 :具體手機--華為手機 */ public class HuaweiMobile extends Mobile{}最后定義一個工廠:
package com.designmode.factory.simple; /** * 類說明 : */ public class MobileFactory {/*** 靜態(tài)工廠方法* @param mobiletype* @return*/public static Mobile product(String mobiletype){Mobile mobile = null; if ("xiaomi".equals(mobiletype)) { mobile = new XiaomiMobile(); System.out.println("生產(chǎn)小米手機."); } else if ("huawei".equals(mobiletype)) { mobile = new HuaweiMobile(); System.out.println("生產(chǎn)華為手機."); } else { System.out.println("不能生產(chǎn)該手機類型."); } return mobile; } }下面咱們來生產(chǎn)手機:
package com.designmode.factory.simple;/** * 類說明 :測試 */ public class Test {public static void main(String[] args) {/*** 客戶要訂購生產(chǎn)小米手機*/MobileFactory.product("xiaomi");/*** 客戶要訂購生產(chǎn)華為手機*/MobileFactory.product("huawei");/*** 客戶要訂購生產(chǎn)錘子手機*/MobileFactory.product("chuizi");} }結(jié)果:
生產(chǎn)小米手機. 生產(chǎn)華為手機. 不能生產(chǎn)該手機類型.2-4、優(yōu)缺點
優(yōu)點:
將創(chuàng)建實例的工作與使用實例的工作分開,使用者不必關(guān)心類對象如何創(chuàng)建,只需要傳入工廠需要的參數(shù)即可;
把初始化實例時的工作放到工廠里進行,使代碼更容易維護;
更符合面向?qū)ο蟮脑瓌t & 面向接口編程;
?缺點:
工廠類集中了所有實例(產(chǎn)品)的創(chuàng)建邏輯,一旦這個工廠不能正常工作,整個系統(tǒng)都會受到影響;
違背“開放 - 關(guān)閉原則”,一旦添加新產(chǎn)品就不得不修改工廠類的邏輯,這樣就會造成工廠邏輯過于復雜,對于系統(tǒng)維護和擴展不夠友好;
簡單工廠模式由于使用了靜態(tài)工廠方法,靜態(tài)方法不能被繼承和重寫,會造成工廠角色無法形成基于繼承的等級結(jié)構(gòu);
2-5、應用場景
(1) 工廠類負責創(chuàng)建的對象比較少,由于創(chuàng)建的對象較少,不會造成工廠方法中的業(yè)務邏輯太過復雜
(2) 客戶端只知道傳入工廠類的參數(shù),對于如何創(chuàng)建對象并不關(guān)心
(3) 鑒于該模式的缺點,因此一般只在很簡單的情況下應用該模式
3、工廠方法模式
3-1、介紹
工廠方法模式,又稱工廠模式、多態(tài)工廠模式和虛擬構(gòu)造器模式,通過定義工廠父類負責定義創(chuàng)建對象的公共接口,而子類則負責生成具體的對象;
抽象工廠是工廠方法模式的核心,所有創(chuàng)建對象的工廠類都必須實現(xiàn)該接口;
英文:Factory Method
? ??定義:定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類,Factory Method使一個類的實例化延遲到了子類;
3-2、解決的問題
工廠一旦需要生產(chǎn)新產(chǎn)品就需要修改工廠類的方法邏輯,違背了“開放 - 關(guān)閉原則“
即簡單工廠模式的缺點
之所以可以解決簡單工廠的問題,是因為工廠方法模式把具體產(chǎn)品的創(chuàng)建推遲到工廠類的子類(具體工廠)中,此時工廠類不再負責所有產(chǎn)品的創(chuàng)建,而只是給出具體工廠必須實現(xiàn)的接口,這樣工廠方法模式在添加新產(chǎn)品的時候就不修改工廠類邏輯而是添加新的工廠子類,符合開放封閉原則,克服了簡單工廠模式中缺點
3-3、實例引入
?定義一個抽象手機類
package com.designmode.factory.method; /** * 類說明 :抽象手機類 */ public abstract class Mobile {}定義一個具體手機類 - 小米手機
package com.designmode.factory.method; /** * 類說明 :具體手機--小米手機 */ public class XiaomiMobile extends Mobile{}定義一個具體手機類 - 華為手機
package com.designmode.factory.method; /** * 類說明 :具體手機--華為手機 */ public class HuaweiMobile extends Mobile{}定義一個抽象工廠接口
package com.designmode.factory.method; /** * 類說明 :抽象手機生產(chǎn)工廠 */ public abstract interface MobileFactory {public abstract Mobile product(); }定義具體工廠 - 小米手機生產(chǎn)工廠
package com.designmode.factory.method; /** * 類說明 :具體工廠類 - 小米工廠 */ public class XiaomiFactory implements MobileFactory{@Overridepublic Mobile product() {System.out.println("生產(chǎn)小米手機.");return new XiaomiMobile();}}定義具體工廠 - 華為手機生產(chǎn)工廠
package com.designmode.factory.method; /** * 類說明 :具體工廠類 - 華為工廠 */ public class HuaweiFactory implements MobileFactory{@Overridepublic Mobile product() {System.out.println("生產(chǎn)華為手機.");return new HuaweiMobile();} }下面測試生產(chǎn)小米手機,華為手機
package com.designmode.factory.method;/** * 類說明 :測試 */ public class Test {public static void main(String[] args) {MobileFactory factory = null;factory = new XiaomiFactory();factory.product();factory = new HuaweiFactory();factory.product();} }結(jié)果:
生產(chǎn)小米手機. 生產(chǎn)華為手機.3-4、優(yōu)缺點
優(yōu)點:
更符合開-閉原則,新增一種產(chǎn)品時,只需要增加相應的具體產(chǎn)品類和相應的工廠子類即可;
符合單一職責原則,每個具體工廠類只負責創(chuàng)建對應的產(chǎn)品;
總結(jié):工廠模式可以說是簡單工廠模式的進一步抽象和拓展,在保留了簡單工廠的封裝優(yōu)點的同時,讓擴展變得簡單,讓繼承變得可行,增加了多態(tài)性的體現(xiàn);
缺點:
添加新產(chǎn)品時,除了增加新產(chǎn)品類外,還要提供與之對應的具體工廠類,系統(tǒng)類的個數(shù)將成對增加,在一定程度上增加了系統(tǒng)的復雜度;同時,有更多的類需要編譯和運行,會給系統(tǒng)帶來一些額外的開銷;
由于考慮到系統(tǒng)的可擴展性,需要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增加了系統(tǒng)的抽象性和理解難度,且在實現(xiàn)時可能需要用到DOM、反射等技術(shù),增加了系統(tǒng)的實現(xiàn)難度;
雖然保證了工廠方法內(nèi)的對修改關(guān)閉,但對于使用工廠方法的類,如果要更換另外一種產(chǎn)品,仍然需要修改實例化的具體工廠類;
一個具體工廠只能創(chuàng)建一種具體產(chǎn)品;
3-5、應用場景
(1) 客戶端不知道它所需要的對象的類。在工廠方法模式中,客戶端不需要知道具體產(chǎn)品類的類名,只需要知道所對應的工廠即可,具體的產(chǎn)品對象由具體工廠類創(chuàng)建;
(2) 抽象工廠類通過其子類來指定創(chuàng)建哪個對象。在工廠方法模式中,對于抽象工廠類只需要提供一個創(chuàng)建產(chǎn)品的接口,而由其子類來確定具體要創(chuàng)建的對象;
4、抽象工廠模式
4-1、介紹
抽象工廠模式為創(chuàng)建一組對象提供了一種解決方案。與工廠方法模式相比,抽象工廠模式中的具體工廠不只是創(chuàng)建一種產(chǎn)品,它負責創(chuàng)建一族產(chǎn)品;
? ?英文:Abstract Factory
定義:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們的具體類;
4-2、解決的問題
每個工廠只能創(chuàng)建一類產(chǎn)品
即工廠方法模式的缺點
4-3、實例引入
?創(chuàng)建一個產(chǎn)品抽象族
package com.designmode.factory.absract; /** * 類說明 :抽象產(chǎn)品族 */ public abstract class AbstractProduct {}創(chuàng)建一個手機抽象類
package com.designmode.factory.absract; /** * 類說明 :抽象手機類 */ public abstract class Mobile extends AbstractProduct{}創(chuàng)建一個MP3抽象類
package com.designmode.factory.absract; /** * 類說明 :抽象MP3類 */ public abstract class MP3 extends AbstractProduct{}創(chuàng)建一個具體手機類 - 小米手機
package com.designmode.factory.absract; /** * 類說明 :具體手機--小米手機 */ public class XiaomiMobile extends Mobile{}創(chuàng)建一個具體手機類 - 華為手機
package com.designmode.factory.absract; /** * 類說明 :具體手機--華為手機 */ public class HuaweiMobile extends Mobile{}創(chuàng)建一個具體MP3類 - 小米MP3
package com.designmode.factory.absract; /** * 類說明 :具體MP3--小米MP3 */ public class XiaomiMP3 extends MP3{}創(chuàng)建一個具體MP3類 - 華為MP3
package com.designmode.factory.absract; /** * 類說明 :具體MP3--華為MP3 */ public class HuaweiMP3 extends MP3{}創(chuàng)建抽象工廠類
package com.designmode.factory.absract; /** * 類說明 :抽象工廠類 */ public abstract interface AbstractFactory {public abstract Mobile productMobile();public abstract MP3 productMP3(); }創(chuàng)建具體工廠類 - 小米工廠
package com.designmode.factory.absract; /** * 類說明 :小米工廠類 */ public class XiaomiFactory implements AbstractFactory{@Overridepublic Mobile productMobile() {System.out.println("生產(chǎn)小米手機.");return new XiaomiMobile();}@Overridepublic MP3 productMP3() {System.out.println("生產(chǎn)小米MP3.");return new XiaomiMP3();}}創(chuàng)建具體工廠類 - 華為工廠
package com.designmode.factory.absract; /** * 類說明 :華為工廠類 */ public class HuaweiFactory implements AbstractFactory{@Overridepublic Mobile productMobile() {System.out.println("生產(chǎn)華為手機.");return new HuaweiMobile();}@Overridepublic MP3 productMP3() {System.out.println("生產(chǎn)華為MP3.");return new HuaweiMP3();}}下面測試一下:生產(chǎn) 小米手機、MP3;華為手機、MP3
package com.designmode.factory.absract; /** * 類說明 :測試 */ public class Test {public static void main(String[] args) {AbstractFactory factory = null;factory = new XiaomiFactory();factory.productMobile();factory.productMP3();factory = new HuaweiFactory();factory.productMobile();factory.productMP3();} }結(jié)果:
生產(chǎn)小米手機. 生產(chǎn)小米MP3. 生產(chǎn)華為手機. 生產(chǎn)華為MP3.4-4、優(yōu)缺點
優(yōu)點:
1)分離接口和實現(xiàn)
客戶端使用抽象工廠來創(chuàng)建需要的對象,而客戶端根本就不知道具體的實現(xiàn)是誰,客戶端只是面向產(chǎn)品的接口編程而已。也就是說,客戶端從具體的產(chǎn)品實現(xiàn)中解耦;
2)使切換產(chǎn)品族變得容易
因為一個具體的工廠實現(xiàn)代表的是一個產(chǎn)品族,拿上面的代碼來說,就是從“小米”到“華為”只需要切換一下具體的工廠即可;
缺點:
1)不太容易擴展新的產(chǎn)品
如果需要給整個產(chǎn)品族添加一個新的產(chǎn)品,那么就需要修改抽象工廠,這樣就會導致修改所有的工廠實現(xiàn)類;
?
3-5、應用場景
? 為創(chuàng)建一組對象提供了一種解決方案;
5、總結(jié)
簡單工廠模式:
簡單工廠類負責了所有產(chǎn)品的創(chuàng)建邏輯,當我們需要新引進一個新產(chǎn)品時,就不得不修改工廠類的產(chǎn)品創(chuàng)建邏輯,在產(chǎn)品類型較多時有可能會造成工廠類的產(chǎn)品創(chuàng)建邏輯過于負責,不利于系統(tǒng)的維護性和擴展性;
工廠方法模式:
對簡單工廠模式的設計優(yōu)化,簡單工廠模式中如果新增一類產(chǎn)品類型時,需要修改工廠靜態(tài)方法的產(chǎn)品創(chuàng)建邏輯,而使用工廠方法模式只需新擴展出一個新的工廠子類或是實現(xiàn)類來針對新增類型產(chǎn)品的創(chuàng)建工作、使系統(tǒng)具有了良好的擴展性與維護性;
抽象工廠模式:
為創(chuàng)建一組對象提供了一種解決方案,與工廠方法模式相比,抽象工廠模式中的具體工廠不只是創(chuàng)建一種產(chǎn)品,它負責創(chuàng)建一族產(chǎn)品;
?
?
PS:源碼地址 ??https://github.com/JsonShare/DesignPattern/tree/master
? ?
PS:原文地址?https://blog.csdn.net/Json_wangqiang/article/details/85276160
?
總結(jié)
以上是生活随笔為你收集整理的设计模式解密(2)- 工厂模式(简单工厂、工厂方法、抽象工厂)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle中的判断大小,sql语句判断
- 下一篇: asp.net ajax控件工具集 Au