介紹:
簡單工廠模式是一種創(chuàng)建型模式脆烟,又叫做靜態(tài)工廠方法模式呐芥。它的定義為:定義一個(gè)用于創(chuàng)建對象的接口,讓子類決定實(shí)例化那個(gè)類圈膏。在簡單工廠模式中,可以根據(jù)參數(shù)的不同返回不同類的實(shí)例篙骡。
類圖:
Product(抽象產(chǎn)品類):要?jiǎng)?chuàng)建的復(fù)雜對象稽坤,抽離通用方法。
ConcreteProduct(具體產(chǎn)品類):實(shí)現(xiàn)Product接口糯俗,即實(shí)現(xiàn)具體方法尿褪。
Factory(工廠類):返回ConcreteProduct實(shí)例,生成ConcreteProduct對象得湘。
用法:
? 生成復(fù)雜對象時(shí)杖玲,確定只有一個(gè)工廠類,可以使用簡單工廠模式淘正。
? 如果直接通過new就可以完成創(chuàng)建的對象無需使用工廠摆马。
個(gè)人理解:
當(dāng)存在一個(gè)業(yè)務(wù),需要用到大量的if-else或switch語句跪帝,并且每個(gè)分支都有一堆相似邏輯的時(shí)候今膊,就可以考慮用簡單工廠模式。簡單工廠可以在不知道具體類的情況下伞剑,只需知道表示具體類的一個(gè)參數(shù)斑唬,并提供一個(gè)創(chuàng)建類的方法。
例子:
在常用的業(yè)務(wù)中黎泣,我們在做一個(gè)App的支付功能時(shí)恕刘,通常會接入微信支付、支付寶支付抒倚、銀行卡支付等的支付通道褐着,下面就用簡單工廠模式去接入支付。
需求:輸入一個(gè)價(jià)格和支付類型托呕,模擬使用不同支付通道的情況含蓉。
1、原始代碼:
在這里例子中所有支付通道的分支都是有相似邏輯的项郊,只需要提供一個(gè)價(jià)格就可以完成支付(實(shí)際情況會復(fù)雜很多馅扣,這里只是簡單舉例)。然后我們很容易的就把代碼寫成下面那樣:
public class Pay {
public void pay(String price, String payType) {
switch (payType) {
case "wechat":
startAilyPay(price);
break;
case "aliy":
startWechatPay(price);
break;
case "union":
startUnionPay(price);
break;
}
}
private void startWechatPay(String price) {
System.out.println("調(diào)起微信SDK着降,價(jià)格:" + price);
}
private void startAliyPay(String price) {
System.out.println("調(diào)起支付寶SDK差油,價(jià)格:" + price);
}
private void startUnionPay(String price) {
System.out.println("調(diào)起銀聯(lián)SDK,價(jià)格:" + price);
}
}
這樣已經(jīng)把支付的邏輯和其它邏輯抽離出來了任洞,看上去還挺不錯(cuò)的蓄喇。但這里如果我們再加入一些新的支付通道发侵,比如京東支付、云閃付等的功能妆偏,需要在pay方法新增分支刃鳄。在代碼良好運(yùn)行的情況下,改動原來的邏輯可能會存在新增bug的風(fēng)險(xiǎn)楼眷。
2铲汪、運(yùn)用簡單工廠模式:
如果我們按照簡單工廠模式的方式,運(yùn)用繼承和多態(tài)的思想把每個(gè)分支都分離出來優(yōu)化代碼罐柳≌蒲看一下效果吧:
2.1、把通用方法抽離张吉,抽象成一個(gè)父類
public abstract class PayChannel {
public abstract void pay(String price);
}
2.2齿梁、每個(gè)通道分別繼承父類
public class AliyPay extends PayChannel {
@Override
public void pay(String price) {
System.out.println("調(diào)起支付寶SDK耕漱,價(jià)格:" + price);
}
}
public class UnionPay extends PayChannel {
@Override
public void pay(String price) {
System.out.println("調(diào)起銀聯(lián)SDK患整,價(jià)格:" + price);
}
}
public class WechatPay extends PayChannel {
@Override
public void pay(String price) {
System.out.println("調(diào)起微信SDK,價(jià)格:" + price);
}
}
2.3涩嚣、建立一個(gè)工廠類(把原始代碼中的Pay方法改一下)
public class PayFactory {
public static PayChannel getPayChannel(String payType) {
PayChannel payChannel = null;
switch (payType) {
case "wechat":
payChannel = new WechatPay();
break;
case "aliy":
payChannel = new AliyPay();
break;
case "union":
payChannel = new UnionPay();
break;
}
return payChannel;
}
}
2.4伦忠、愉快地調(diào)用吧
public class PayTest {
public static void main(String[] args) {
/*
PayChannel payChannel = PayFactory.getPayChannel("aliy");
payChannel.pay("100元");
PayChannel payChannel = PayFactory.getPayChannel("union");
payChannel.pay("100元");
*/
PayChannel payChannel = PayFactory.getPayChannel("wechat");
payChannel.pay("100元");
}
}
運(yùn)用了簡單工廠模式之后省核,運(yùn)用不同通道只需要修改payType參數(shù)即可。當(dāng)我們需要新增支付通道時(shí)昆码,增加相應(yīng)的支付子類即可气忠,最后在工廠類的switch中新建分支。這里已經(jīng)滿足了簡單工廠模式的要求了赋咽,但有沒有一個(gè)更優(yōu)化的方式呢旧噪?
3、簡單工廠模式的優(yōu)化:
我們新增代碼的時(shí)候還是要改動原來的代碼脓匿,明顯違反了開閉原則淘钟。在Java中,可以通過反射的方式去創(chuàng)建實(shí)例陪毡。
3.1米母、修改一下PayFactory類
public class PayFactory {
public static PayChannel getPayChannel(Class<? extends PayChannel> clz){
PayChannel payChannel = null;
try {
payChannel = (PayChannel) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return payChannel;
}
}
3.2、再運(yùn)行一下代碼
public class PayTest {
public static void main(String[] args) {
/*
PayChannel payChannel = PayFactory.getPayChannel("wechat");
payChannel.pay("100元");
*/
PayChannel payChannel = PayFactory.getPayChannel(AliyPay.class);
payChannel.pay("200元");
}
}
注意一下毡琉,不是所有語言都能用這種方法爱咬。新增支付子類時(shí)不需要在工廠類中增加分支,符合了開閉原則绊起,但反射會影響性能。任君選擇吧~
感謝您的閱讀~
轉(zhuǎn)載請注明出處喔:http://www.reibang.com/p/b3600a262c38
推薦閱讀
基礎(chǔ)篇:
設(shè)計(jì)模式前篇之——UML類圖必會知識點(diǎn)
設(shè)計(jì)模式前篇之——一起過一下面向?qū)ο蟮母拍?/a>
創(chuàng)建型模式:
簡易理解設(shè)計(jì)模式之:簡單工廠模式——來試試接入支付功能
簡易理解設(shè)計(jì)模式之:工廠方法模式——數(shù)據(jù)存儲例子
簡易理解設(shè)計(jì)模式之:抽象工廠模式——更換數(shù)據(jù)庫例子
簡易理解設(shè)計(jì)模式之:建造者模式——學(xué)習(xí)使用“鏈?zhǔn)秸{(diào)用”
簡易理解設(shè)計(jì)模式之:原型模式——深燎斩、淺拷貝的概念
簡易理解設(shè)計(jì)模式之:單例模式——單例模式的幾種常用寫法
結(jié)構(gòu)型模式:
簡易理解設(shè)計(jì)模式之:適配器模式——Android列表視圖控件設(shè)計(jì)方式
簡易理解設(shè)計(jì)模式之:橋接模式——穿衣服經(jīng)典案例2
簡易理解設(shè)計(jì)模式之:組合模式——實(shí)現(xiàn)View中的樹狀結(jié)構(gòu)
簡易理解設(shè)計(jì)模式之:裝飾模式——穿衣服經(jīng)典案例
簡易理解設(shè)計(jì)模式之:外觀模式——第三方SDK的幫助類
簡易理解設(shè)計(jì)模式之:享元模式——五子棋游戲例子
簡易理解設(shè)計(jì)模式之:代理模式——iOS視圖控件設(shè)計(jì)方式
行為型模式:
簡易理解設(shè)計(jì)模式之:策略模式——優(yōu)化一下支付功能
簡易理解設(shè)計(jì)模式之:模板方法模式——Android中的BaseActivity基類
簡易理解設(shè)計(jì)模式之:觀察者模式——監(jiān)聽與回調(diào)
簡易理解設(shè)計(jì)模式之:狀態(tài)模式——優(yōu)化登錄操作
簡易理解設(shè)計(jì)模式之:備忘錄模式——Word文檔的工作原理
簡易理解設(shè)計(jì)模式之:迭代器模式——遍歷對象的好幫手
簡易理解設(shè)計(jì)模式之:命令模式——實(shí)現(xiàn)命令的參數(shù)化配置
簡易理解設(shè)計(jì)模式之:責(zé)任鏈模式——OA中請假流程示例
簡易理解設(shè)計(jì)模式之:中介者模式——多人聊天室例子
簡易理解設(shè)計(jì)模式之:解釋器模式——語言和文法
簡易理解設(shè)計(jì)模式之:訪問者模式——員工考核例子