簡易理解設(shè)計(jì)模式之:簡單工廠模式——來試試接入支付功能

介紹:

簡單工廠模式是一種創(chuàng)建型模式脆烟,又叫做靜態(tài)工廠方法模式呐芥。它的定義為:定義一個(gè)用于創(chuàng)建對象的接口,讓子類決定實(shí)例化那個(gè)類圈膏。在簡單工廠模式中,可以根據(jù)參數(shù)的不同返回不同類的實(shí)例篙骡。

類圖:

簡單工廠模式UML類圖

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ì)模式之:訪問者模式——員工考核例子

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虱歪,一起剝皮案震驚了整個(gè)濱河市蜂绎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笋鄙,老刑警劉巖师枣,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異萧落,居然都是意外死亡践美,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門找岖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陨倡,“玉大人,你說我怎么就攤上這事许布⌒烁铮” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵蜜唾,是天一觀的道長杂曲。 經(jīng)常有香客問我,道長袁余,這世上最難降的妖魔是什么擎勘? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮颖榜,結(jié)果婚禮上棚饵,老公的妹妹穿的比我還像新娘。我一直安慰自己朱转,他們只是感情好蟹地,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著藤为,像睡著了一般怪与。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缅疟,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天分别,我揣著相機(jī)與錄音,去河邊找鬼存淫。 笑死耘斩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桅咆。 我是一名探鬼主播括授,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荚虚?” 一聲冷哼從身側(cè)響起薛夜,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎版述,沒想到半個(gè)月后梯澜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡渴析,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年晚伙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俭茧。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咆疗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恢恼,到底是詐尸還是另有隱情民傻,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布场斑,位于F島的核電站漓踢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏漏隐。R本人自食惡果不足惜喧半,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望青责。 院中可真熱鬧挺据,春花似錦、人聲如沸脖隶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽产阱。三九已至婉称,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間构蹬,已是汗流浹背王暗。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留庄敛,地道東北人俗壹。 一個(gè)月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像藻烤,于是被迫代替她去往敵國和親绷雏。 傳聞我的和親對象是個(gè)殘疾皇子头滔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345