初学Java常用设计模式之——工厂模式
聲明:轉(zhuǎn)載請附上原文鏈接
提示:標(biāo)題序號從2開始,是照應(yīng)不同設(shè)計(jì)模式筆記發(fā)布的順序而定的,比如,第上一篇文章 初學(xué)Java常用設(shè)計(jì)模式之——單例模式 序號從1開始
2. 工廠模式(常用)
-
??模式介紹:
- 它提供了?種創(chuàng)建對象的最佳?式,我們在創(chuàng)建對象時 不會對客戶端暴露創(chuàng)建邏輯,并且是通過使??個共同 的接?來指向新創(chuàng)建的對象。
-
例?:
- ???產(chǎn)電腦,除了A品牌、還可以?產(chǎn)B、C、D品牌 電腦;
- 業(yè)務(wù)開發(fā)中,?付很常?,??有統(tǒng)?下單和?付接 ?,具體的?付實(shí)現(xiàn)可以微信、?付寶、銀?卡等;
-
??模式有 3 種不同的實(shí)現(xiàn)?式:
- 簡單??模式:通過傳?相關(guān)的類型來返回相應(yīng)的類,這 種?式?較單 ?,可擴(kuò)展性相對較差;
- ???法模式:通過實(shí)現(xiàn)類實(shí)現(xiàn)相應(yīng)的?法來決定相應(yīng) 的返回結(jié)果,這種?式的可擴(kuò)展性?較強(qiáng);
- 抽象??模式:基于上述兩種模式的拓展,且?持細(xì)化 產(chǎn)品;
-
應(yīng)?場景:
- 解耦:分離職責(zé),把復(fù)雜對象的創(chuàng)建和使?的過程分開
- 復(fù)?代碼 降低維護(hù)成本:
- 如果對象創(chuàng)建復(fù)雜且多處需?到,如果每處都進(jìn)?編寫,則很多重復(fù)代碼,如果業(yè)務(wù)邏輯發(fā)?了改 變,需?四處修改;
- 使???模式統(tǒng)?創(chuàng)建,則只要修改??類即可, 降低成本;
2.1 工廠模式——簡單工廠模式
- 簡單??模式(靜態(tài)工廠)
- ?稱靜態(tài)???法, 可以根據(jù)參數(shù)的不同返回不同類的實(shí)例,專?定義?個類來負(fù)責(zé)創(chuàng)建其他類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的?類;
- 由于???法是靜態(tài)?法,可通過類名直接調(diào)?,?且只需要傳?簡單的參數(shù)即可;
- 核?組成
- Factory:??類,簡單??模式的核?,它負(fù)責(zé)實(shí)現(xiàn) 創(chuàng)建所有實(shí)例的內(nèi)部邏輯
- IProduct:抽象產(chǎn)品類,簡單??模式所創(chuàng)建的所有對象的?類,描述所有實(shí)例所共有的公共接?
- Product:具體產(chǎn)品類,是簡單??模式的創(chuàng)建?標(biāo)
- 實(shí)現(xiàn)步驟
- 創(chuàng)建抽象產(chǎn)品類,??有產(chǎn)品的抽象?法,由具體的產(chǎn) 品類去實(shí)現(xiàn)
- 創(chuàng)建具體產(chǎn)品類,繼承了他們的?類,并實(shí)現(xiàn)具體?法
- 創(chuàng)建??類,提供了?個靜態(tài)?法createXXX()?來?產(chǎn)產(chǎn)品,只需要傳?你想產(chǎn)品名稱
- 優(yōu)點(diǎn):
- 將對象的創(chuàng)建和對象本身業(yè)務(wù)處理分離可以降低系統(tǒng)的 耦合度,使得兩者修改起來都相對容易。
- 缺點(diǎn):
- ??類的職責(zé)相對過重,增加新的產(chǎn)品需要修改??類的判斷邏輯,這?點(diǎn)與開閉原則是相違背
- 即開閉原則(Open Close Principle)對擴(kuò)展開放,對 修改關(guān)閉,程序需要進(jìn)?拓展的時候,不能去修改原有 的代碼,實(shí)現(xiàn)?個熱插拔的效果
- 將會增加系統(tǒng)中類的個數(shù),在?定程度上增加了系統(tǒng)的復(fù)雜度和理解難度,不利于系統(tǒng)的擴(kuò)展和維護(hù),創(chuàng)建簡單對象就不?模式
下面我們來簡單使用一下簡單(靜態(tài))工廠設(shè)計(jì)模式:
功能描述:
我們簡單使用偽代碼模擬一下支付流程:
創(chuàng)建IProduct 抽象產(chǎn)品接口——IPay
/*** @Auther: csp1999* @Date: 2020/11/07/11:00* @Description: IPay抽象統(tǒng)一支付下單接口*/ public interface IPay {/*** 統(tǒng)一下單*/void unifiedOrder(); }創(chuàng)建Product具體產(chǎn)品類——AliPay/WeChatPay
AliPay.java
/*** @Auther: csp1999* @Date: 2020/11/07/11:29* @Description: 支付寶支付具體實(shí)現(xiàn)類*/ public class AliPay implements IPay{@Overridepublic void unifiedOrder() {System.out.println("支付寶支付統(tǒng)一下單...");} }WeChatPay.java
/*** @Auther: csp1999* @Date: 2020/11/07/11:30* @Description: 微信支付具體實(shí)現(xiàn)類*/ public class WeChatPay implements IPay{@Overridepublic void unifiedOrder() {System.out.println("微信支付統(tǒng)一下單...");} }創(chuàng)建Factory工廠類——SimplePayFactory
/*** @Auther: csp1999* @Date: 2020/11/07/11:31* @Description: 簡單支付工廠類(靜態(tài)工廠類)*/ public class SimplePayFactory {/*** 工廠創(chuàng)建方法:* 根據(jù)參數(shù)返回對應(yīng)的支付對象** @param payType* @return*/public static IPay createPay(String payType) {if (payType == null) {return null;} else if (payType.equalsIgnoreCase("WECHAT_PAY")) {return new WeChatPay();} else if (payType.equalsIgnoreCase("ALI_PAY")) {return new AliPay();}// 如果需要擴(kuò)展,可以編寫更剁return null;} }測試使用簡單支付工廠:
@Test public void testSimplePayFactory(){IPay wechat_pay = SimplePayFactory.createPay("WECHAT_PAY");IPay ali_pay = SimplePayFactory.createPay("ALI_PAY");wechat_pay.unifiedOrder();ali_pay.unifiedOrder(); }// 輸出結(jié)果: // 微信支付統(tǒng)一下單... // 支付寶支付統(tǒng)一下單...上述就是工廠設(shè)計(jì)模式——簡單工程(靜態(tài)工廠的一個簡單使用例子),那么我們來分析下其缺點(diǎn)與不足之處:
需求:
- 如果我需要額外再添加一個A銀行的銀行卡支付,那么就需要在SimplePayFactory 類中添加響應(yīng)的判斷邏輯,比如再加一個if判斷,添加一個A銀行支付的邏輯
- 而如果再需要一個B銀行的銀行卡支付,那么還需要再添加一個if判斷 添加一個B銀行支付的邏輯,依次加下去…
- 那么這就違背了??類要遵循的開閉原則(Open Close Principle)(對擴(kuò)展開放,對修改關(guān)閉,程序需要進(jìn)?拓展的時候,不能去修改原有的代碼,實(shí)現(xiàn)?個熱插拔的效果),這樣就導(dǎo)致,每次擴(kuò)展功能的時候都需要添加新的邏輯,并且需要對工廠類進(jìn)行修改,如果是真實(shí)復(fù)雜的業(yè)務(wù),這就增加了成本。
下面我們來看一下工廠方法模式是如何解決簡單工廠模式的這一缺點(diǎn)
2.2 工廠模式——工廠方法模式
- ???法模式
- ?稱??模式,是對簡單??模式的進(jìn)?步抽象化,其 好處是可以使系統(tǒng)在不修改原來代碼的情況下引進(jìn)新的 產(chǎn)品,即滿?開閉原則
- 通過???類定義負(fù)責(zé)創(chuàng)建產(chǎn)品的公共接?,通過?類 來確定所需要創(chuàng)建的類型
- 相?簡單????,此種?法具有更多的可擴(kuò)展性和復(fù)?性,同時也增強(qiáng)了代碼的可讀性
- 將類的實(shí)例化(具體產(chǎn)品的創(chuàng)建)延遲到??類的?類 (具體??)中完成,即由?類來決定應(yīng)該實(shí)例化哪? 個類
- 核?組成
- IProduct:抽象產(chǎn)品接口,描述所有實(shí)例所共有的公共接?
- Product:具體產(chǎn)品類,實(shí)現(xiàn)抽象產(chǎn)品類的接?,?? 類創(chuàng)建對象,如果有多個需要定義多個
- IFactory:抽象??接口,描述具體??的公共接?
- Factory:具體??類,實(shí)現(xiàn)創(chuàng)建產(chǎn)品類對象,實(shí)現(xiàn)抽 象??類的接?,如果有多個需要定義多個
要實(shí)現(xiàn)工廠方法模式,只需要在原來的簡單工廠模式基礎(chǔ)上,做出改進(jìn),而之前我們創(chuàng)建的IPay抽象產(chǎn)品接口和AliPay WeChatPay 兩個具體產(chǎn)品類不需要改動。
首先創(chuàng)建IPayFactory抽象??接口:
/*** @Auther: csp1999* @Date: 2020/11/07/15:08* @Description: 抽象??接口*/ public interface IPayFactory {IPay getPay(); }然后創(chuàng)建AliPayFactory和WeChatFactory 兩個具體??類:
/*** @Auther: csp1999* @Date: 2020/11/07/15:09* @Description: 具體工廠類 AliPayFactory*/ public class AliPayFactory implements IPayFactory{@Overridepublic IPay getPay() {return new AliPay();} } /*** @Auther: csp1999* @Date: 2020/11/07/15:16* @Description: 具體工廠類 WeChatFactory*/ public class WeChatFactory implements IPayFactory{@Overridepublic IPay getPay() {return new WeChatPay();} }進(jìn)行測試:
@Test public void testMethodPayFactory(){AliPayFactory aliPayFactory = new AliPayFactory();IPay ali_pay = aliPayFactory.getPay();ali_pay.unifiedOrder();// 輸出:支付寶支付統(tǒng)一下單...WeChatFactory weChatFactory = new WeChatFactory();IPay wechat_pay = weChatFactory.getPay();wechat_pay.unifiedOrder();// 輸出:微信支付統(tǒng)一下單... }工廠方法模式思路如下圖:
- 工廠方法模式優(yōu)點(diǎn):
- 符合開閉原則,增加?個產(chǎn)品類,只需要實(shí)現(xiàn)其他具體的產(chǎn)品類和具體的??類;
- 符合單?職責(zé)原則,每個??只負(fù)責(zé)?產(chǎn)對應(yīng)的產(chǎn)品;
- 使?者只需要知道產(chǎn)品的抽象類,?須關(guān)?其他實(shí)現(xiàn) 類,滿?迪?特法則、依賴倒置原則和??替換原則;
- 迪?特法則:最少知道原則,實(shí)體應(yīng)當(dāng)盡量少地與 其他實(shí)體之間發(fā)?相互作?;
- 依賴倒置原則:針對接?編程,依賴于抽象?不依 賴于具體;
- ??替換原則:俗稱LSP, 任何基類可以出現(xiàn)的地 ?,?類?定可以出現(xiàn), 對實(shí)現(xiàn)抽象化的具體步驟的 規(guī)范;
- 工廠方法模式缺點(diǎn):
- 增加?個產(chǎn)品,需要實(shí)現(xiàn)對應(yīng)的具體??類和具體產(chǎn)品類;
- 每個產(chǎn)品需要有對應(yīng)的具體??和具體產(chǎn)品類;
2.3 工廠模式——抽象工廠方法模式
抽象???法模式是簡單工廠模式 和工廠方法模式的整合升級版。
- ??模式有 3 種不同的實(shí)現(xiàn)?式:
- 簡單??模式:通過傳?相關(guān)的類型來返回相應(yīng)的類,這 種?式?較單 ?,可擴(kuò)展性相對較差;
- ???法模式:通過實(shí)現(xiàn)類實(shí)現(xiàn)相應(yīng)的?法來決定相應(yīng) 的返回結(jié)果,這種?式的可擴(kuò)展性?較強(qiáng);
- 抽象??模式:基于上述兩種模式的拓展,是???法 模式的升級版,當(dāng)需要創(chuàng)建的產(chǎn)品有多個產(chǎn)品線時使? 抽象??模式是?較好的選擇
- 抽象??模式在 Spring 中應(yīng)?得最為?泛的?種設(shè)計(jì)模式
- 背景:
- ???法模式引???等級結(jié)構(gòu),解決了簡單??模式 中??類職責(zé)過重的問題
- 但???法模式中每個??只創(chuàng)建?類具體類的對象, 后續(xù)發(fā)展可能會導(dǎo)致??類過多,因此將?些相關(guān)的具 體類組成?個“具體類族”,由同?個??來統(tǒng)??產(chǎn), 強(qiáng)調(diào)的是?系列相關(guān)的產(chǎn)品對象!!!
- 實(shí)現(xiàn)步驟:
- 1、定義兩個接? IPay(支付)、IRefund(退款)
- 2、創(chuàng)建具體的Pay產(chǎn)品、創(chuàng)建具體的Refund產(chǎn)品
- 3、創(chuàng)建抽象?? IOrderFactory 接? ??兩個?法 createPay/createRefund
- 4、創(chuàng)建?付寶產(chǎn)品族AliOderFactory,實(shí)現(xiàn)OrderFactory 抽象??
- 5、創(chuàng)建微信?付產(chǎn)品族WechatOderFactory,實(shí)現(xiàn) OrderFactory抽象??
- 6、定義?個超級??創(chuàng)造器FactoryProducer,通過傳遞參數(shù)獲取對應(yīng)的??
接下來我們就按照步驟使用一下抽象工廠方法模式:
1、定義兩個接? IPay(支付)、IRefund(退款):
/*** @Auther: csp1999* @Date: 2020/11/07/16:06* @Description: 支付抽象接口*/ public interface IPay {/*** 統(tǒng)一下單*/void unifiedOrder(); } /*** @Auther: csp1999* @Date: 2020/11/07/16:07* @Description: 退款抽象接口*/ public interface IReFund {/*** 退款*/void refund(); }2、創(chuàng)建具體的Pay產(chǎn)品、創(chuàng)建具體的Refund產(chǎn)品:
AliPay/WeChatPay:支付寶支付和微信支付
/*** @Auther: csp1999* @Date: 2020/11/07/11:29* @Description: 支付寶支付具體實(shí)現(xiàn)類*/ public class AliPay implements IPay {@Overridepublic void unifiedOrder() {System.out.println("支付寶支付 統(tǒng)一下單接口...");} } /*** @Auther: csp1999* @Date: 2020/11/07/11:30* @Description: 微信支付具體實(shí)現(xiàn)類*/ public class WeChatPay implements IPay {@Overridepublic void unifiedOrder() {System.out.println("微信支付統(tǒng)一下單...");} }AliRefund/WeChatFund:支付寶退款和微信退款
/*** @Auther: csp1999* @Date: 2020/11/07/16:35* @Description:*/ public class AliRefund implements IReFund {@Overridepublic void refund() {System.out.println("支付寶退款...");} } /*** @Auther: csp1999* @Date: 2020/11/07/16:40* @Description:*/ public class WeChatRefund implements IReFund {@Overridepublic void refund() {System.out.println("微信支付退款...");} }3、創(chuàng)建抽象?? IOrderFactory 接? ??兩個?法 createPay/createRefund:
/*** @Auther: csp1999* @Date: 2020/11/07/16:04* @Description: 訂單抽象工廠,一個超級工廠可以創(chuàng)建其他工廠(又被稱為其他工廠的工廠)*/ public interface IOrderFactory {IPay createPay();IReFund createRefund(); }4、創(chuàng)建?付寶產(chǎn)品族AliOderFactory,實(shí)現(xiàn)OrderFactory 抽象??:
/*** @Auther: csp1999* @Date: 2020/11/07/16:18* @Description:*/ public class AliOrderFactory implements IOrderFactory {@Overridepublic IPay createPay() {return new AliPay();}@Overridepublic IReFund createRefund() {return new AliRefund();} }5、創(chuàng)建微信?付產(chǎn)品族WechatOderFactory,實(shí)現(xiàn) OrderFactory抽象??
/*** @Auther: csp1999* @Date: 2020/11/07/16:39* @Description:*/ public class WeChatOrderFactory implements IOrderFactory {@Overridepublic IPay createPay() {return new WeChatPay();}@Overridepublic IReFund createRefund() {return new WeChatRefund();} }6、定義?個超級??創(chuàng)造器FactoryProducer,通過傳遞參數(shù)獲取對應(yīng)的??
/*** @Auther: csp1999* @Date: 2020/11/07/16:46* @Description: 工廠創(chuàng)造器*/ public class FactoryProducer {public static IOrderFactory getFactory(String type){if (type.equalsIgnoreCase("WECHAT")){return new WeChatOrderFactory();}else if (type.equalsIgnoreCase("ALI")){return new AliOrderFactory();}return null;} }最后我們來進(jìn)行測試:
@Test public void testAbstractMethodPayFactory(){IOrderFactory wechatPayFactory = FactoryProducer.getFactory("WECHAT");wechatPayFactory.createPay().unifiedOrder();wechatPayFactory.createRefund().refund();IOrderFactory aliPayFactory = FactoryProducer.getFactory("ALI");aliPayFactory.createPay().unifiedOrder();aliPayFactory.createRefund().refund(); }結(jié)果如下:
微信支付統(tǒng)一下單... 微信支付退款... 支付寶支付 統(tǒng)一下單接口... 支付寶退款...- ???法模式和抽象???法模式
- 當(dāng)抽象??模式中每?個具體??類只創(chuàng)建?個產(chǎn)品對 象,抽象??模式退化成???法模式
- 優(yōu)點(diǎn)
- 當(dāng)?個產(chǎn)品族中的多個對象被設(shè)計(jì)成?起?作時,它能 保證使??始終只使?同?個產(chǎn)品族中的對象
- 產(chǎn)品等級結(jié)構(gòu)擴(kuò)展容易,如果需要增加多?個產(chǎn)品等 級,只需要增加新的??類和產(chǎn)品類即可, ?如增加銀 ??付、退款
- 缺點(diǎn)
- 產(chǎn)品族擴(kuò)展困難,要增加?個系列的某?產(chǎn)品,既要在 抽象的??和抽象產(chǎn)品?修改代碼,不是很符合開閉原 則
- 增加了系統(tǒng)的抽象性和理解難度
之后我會陸續(xù)更新其他設(shè)計(jì)模式博文,如果文章對您有幫助,希望點(diǎn)個贊/收藏/關(guān)注! O(∩_∩)O~
總結(jié)
以上是生活随笔為你收集整理的初学Java常用设计模式之——工厂模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces Round #54
- 下一篇: Java Comparator使用指南