【阿里大神講設(shè)計(jì)模式】3.光氏飲品升級(jí)了---工廠方法模式

前情提要


上集講到, 小光的熱干面店, 開(kāi)始搭配提供飲料了. 再加上美女表妹的助陣, 生意是紅紅火火啊.
然而, 事情也不是盡善盡美的, 慢慢小光就聽(tīng)到了一些的客戶(hù)的聲音: 酸梅湯太酸了, 能調(diào)好點(diǎn)嗎? 天冷了能來(lái)點(diǎn)熱飲嗎?
客戶(hù)可是上帝啊, 小光立馬就著手改進(jìn).

所有示例源碼已經(jīng)上傳到Github, 戳這里

表妹的抱怨


帶著客戶(hù)的聲音, 小光找表妹聊了下, 想讓表妹修改下當(dāng)前的酸梅湯泡制比例, 另外再增加一些熱飲的泡制.
沒(méi)想到, 表妹一聽(tīng)到著就很反對(duì): “我現(xiàn)在已經(jīng)記得太多了, 你這么不定時(shí)的修改, 增加, 我更容易記混, 到時(shí)候更出問(wèn)題了”. (職責(zé)太重)
小光一想, 是啊, 我把自己從做熱干面添加各種配料的煩惱中釋放出來(lái)了(通過(guò)Builder模式). 不能讓表妹也陷入這樣的煩惱啊.

解決之路


可是怎么才能更好的解決這個(gè)問(wèn)題呢?
要是我有很多個(gè)表妹就好了, 每個(gè)表妹負(fù)責(zé)一種飲料的泡制, 小光想著. 嗯~, 很多個(gè)表妹?! 小光微微一笑, 計(jì)上心頭.
小光買(mǎi)來(lái)很多個(gè)迷你飲水機(jī), 一個(gè)裝一種飲料, 并且貼上相應(yīng)的標(biāo)簽, 如此這般:


每個(gè)迷你飲水機(jī)作為一個(gè)飲料機(jī), 用來(lái)生產(chǎn)不同的飲料. 表妹只有根據(jù)用戶(hù)的需求選擇不同的飲料機(jī)打出飲料即可.
這樣, 表妹也無(wú)需關(guān)注飲料的生產(chǎn)過(guò)程了, 不用記那么多的飲料配置方式了. 如果想要新增飲品, 再弄一臺(tái)飲料機(jī)就行了.

來(lái)看看對(duì)應(yīng)關(guān)系


這是沒(méi)有標(biāo)簽的飲水機(jī)(飲料機(jī)):

public interface IBeverageMachine {

    Drink makeDrink();
}

這是貼了不同飲料類(lèi)型的飲料機(jī):

public class OrangeJuiceMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink() {
        return new OrangeJuice().make();
    }
}
public class CokeMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink() {
        return new Coke().make();
    }
}
public class PlumJuiceMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink() {
        return new PlumJuice().make();
    }
}

這是那些飲料(還是有一個(gè)抽象繼承關(guān)系):

public abstract class Drink {

    private String name;
    private String instantPackage;

    public Drink make() {
        this.name = getName();
        this.instantPackage = getInstantPackage();
        return this;
    }

    abstract String getInstantPackage();
    abstract String getName();

    @Override
    public String toString() {
        return "This is a cup of:" + this.name;
    }
}

public class Coke extends Drink {
    @Override
    String getInstantPackage() {
        return "速溶可樂(lè)粉";
    }

    @Override
    String getName() {
        return "可樂(lè)";
    }
}

public class OrangeJuice extends Drink {
    @Override
    String getInstantPackage() {
        return "速溶橙汁粉";
    }

    @Override
    String getName() {
        return "橙汁";
    }
}

public class PlumJuice extends Drink {
    @Override
    String getInstantPackage() {
        return "速溶酸梅粉";
    }

    @Override
    String getName() {
        return "酸梅湯";
    }
}

相比上一篇簡(jiǎn)單工廠中的飲料, 我們將打包這個(gè)操作從飲料這個(gè)對(duì)象中移除了, 目前的飲料對(duì)象中只是一些簡(jiǎn)單的屬性.
為什么要這么做呢? 大家可以用自己面向?qū)ο缶幊趟枷氲哪X洞自由發(fā)揮下, 下期說(shuō)說(shuō)我的想法.

現(xiàn)在表妹的工作就變得簡(jiǎn)單了:

public class Cousins {

    private IBeverageMachine mBeverageMachine;

    private void setBeverageMachine(IBeverageMachine machine) {
        this.mBeverageMachine = machine;
    }

    private Drink takeDrink() {
        if (mBeverageMachine == null) throw new NullPointerException("Should set Beverage Machine firstly.");

        return mBeverageMachine.makeDrink();
    }

    public static void main(String[] args) {

        Cousins cousins = new Cousins();

        // for A
        cousins.setBeverageMachine(new OrangeJuiceMachine());
        Drink drink = cousins.takeDrink();
        System.out.println(drink);

        // for B
        cousins.setBeverageMachine(new CokeMachine());
        System.out.println(cousins.takeDrink());
    }
}

當(dāng)A要橙汁時(shí), 表妹去OrangeJuiceMachine裝一杯, 當(dāng)B需要可樂(lè)時(shí), 表妹再去CokeMachine拿:

This is a cup of:橙汁
This is a cup of:可樂(lè)

表妹的工作變得更簡(jiǎn)單了, 工作效率也更高了, 也更能微笑面對(duì)顧客了, 哈哈…

想要奶茶的C顧客


這天, 來(lái)了一位顧客D, 問(wèn): “老板, 有沒(méi)有熱奶茶啊?”. 考驗(yàn)小光的程序的時(shí)候到了. 很快, 小光copy出了一個(gè)奶茶機(jī)(擴(kuò)展開(kāi)放), 同時(shí)也無(wú)需修改原來(lái)的那些個(gè)飲料機(jī)程序(修改關(guān)閉), 不會(huì)因此而耽誤生意.
新增奶茶飲料:

public class MilkTea extends Drink {
    @Override
    String getInstantPackage() {
        return "速溶奶茶粉";
    }
    @Override
    String getName() {
        return "奶茶";
    }
}

奶茶機(jī):

public class MilkTeaMachine implements IBeverageMachine {
    @Override
    public Drink makeDrink() {
        return new MilkTea().make();
    }
}

現(xiàn)在的臺(tái)面:

表妹的工作也很簡(jiǎn)單, 去奶茶機(jī)那兒接奶茶就是了:

// for D
cousins.setBeverageMachine(new MilkTeaMachine());
System.out.println(cousins.takeDrink());

D拿到的:

This is a cup of:奶茶

故事之后

照例, 我們先來(lái)畫(huà)出現(xiàn)在的類(lèi)對(duì)應(yīng)關(guān)系:
實(shí)際上這個(gè)就是工廠方法模式.

幾個(gè)點(diǎn):
1, 為何叫工廠方法, 是因?yàn)槊總€(gè)工廠有一個(gè)方法來(lái)創(chuàng)建產(chǎn)品.
2, 每個(gè)產(chǎn)品對(duì)應(yīng)一個(gè)工廠實(shí)例來(lái)生產(chǎn)這個(gè)產(chǎn)品實(shí)例.
3, 因?yàn)楫a(chǎn)品和其對(duì)應(yīng)的工廠都與其他產(chǎn)品分離, 我們可以很輕易的去增加新的產(chǎn)品和其對(duì)應(yīng)的工廠, 而不改變?cè)瓉?lái)的結(jié)構(gòu). (開(kāi)閉原則, 實(shí)際上還蘊(yùn)含了職責(zé)單一)

擴(kuò)展閱讀


工廠方法模式如同Buidler模式, 是一些開(kāi)源庫(kù)中非常常見(jiàn)的用來(lái)創(chuàng)建實(shí)例的設(shè)計(jì)模式.
例如OkHttp中ModelLoader相關(guān)的實(shí)現(xiàn):


看對(duì)應(yīng)關(guān)系就跟清晰了, 就不一一類(lèi)比了.
小光看著這一排飲料機(jī), 成就感悠然而生, 仿佛又回到了那個(gè)徹夜編碼的歲月.


原文地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子未檩,更是在濱河造成了極大的恐慌用爪,老刑警劉巖障癌,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纠亚,死亡現(xiàn)場(chǎng)離奇詭異蝶糯,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)样眠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)翠肘,“玉大人檐束,你說(shuō)我怎么就攤上這事∈叮” “怎么了被丧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)肌幽。 經(jīng)常有香客問(wèn)我晚碾,道長(zhǎng),這世上最難降的妖魔是什么喂急? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任格嘁,我火速辦了婚禮,結(jié)果婚禮上廊移,老公的妹妹穿的比我還像新娘糕簿。我一直安慰自己,他們只是感情好狡孔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布懂诗。 她就那樣靜靜地躺著,像睡著了一般苗膝。 火紅的嫁衣襯著肌膚如雪殃恒。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音离唐,去河邊找鬼病附。 笑死,一個(gè)胖子當(dāng)著我的面吹牛亥鬓,可吹牛的內(nèi)容都是我干的完沪。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嵌戈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼覆积!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起熟呛,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宽档,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后惰拱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雌贱,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年偿短,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欣孤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昔逗,死狀恐怖降传,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勾怒,我是刑警寧澤婆排,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站笔链,受9級(jí)特大地震影響段只,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鉴扫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一赞枕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坪创,春花似錦炕婶、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至依沮,卻和暖如春涯贞,著一層夾襖步出監(jiān)牢的瞬間枪狂,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工肩狂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摘完,地道東北人姥饰。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓傻谁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親列粪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子审磁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容