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

本設(shè)計模式系列文章由阿里大神 名俊 授權(quán)發(fā)布

前情提要

上集講到, 小光的熱干面店, 開始搭配提供飲料了. 再加上美女表妹的助陣, 生意是紅紅火火啊.

然而, 事情也不是盡善盡美的, 慢慢小光就聽到了一些的客戶的聲音: 酸梅湯太酸了, 能調(diào)好點嗎? 天冷了能來點熱飲嗎?

客戶可是上帝啊, 小光立馬就著手改進(jìn).

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

表妹的抱怨

帶著客戶的聲音, 小光找表妹聊了下, 想讓表妹修改下當(dāng)前的酸梅湯泡制比例, 另外再增加一些熱飲的泡制.

沒想到, 表妹一聽到著就很反對: "我現(xiàn)在已經(jīng)記得太多了, 你這么不定時的修改, 增加, 我更容易記混, 到時候更出問題了". (職責(zé)太重)

小光一想, 是啊, 我把自己從做熱干面添加各種配料的煩惱中釋放出來了(通過Builder模式). 不能讓表妹也陷入這樣的煩惱啊.

解決之路

可是怎么才能更好的解決這個問題呢?
要是我有很多個表妹就好了, 每個表妹負(fù)責(zé)一種飲料的泡制, 小光想著. 嗯~, 很多個表妹?! 小光微微一笑, 計上心頭.

小光買來很多個迷你飲水機, 一個裝一種飲料, 并且貼上相應(yīng)的標(biāo)簽, 如此這般:


每個迷你飲水機作為一個飲料機, 用來生產(chǎn)不同的飲料. 表妹只有根據(jù)用戶的需求選擇不同的飲料機打出飲料即可.

這樣, 表妹也無需關(guān)注飲料的生產(chǎn)過程了, 不用記那么多的飲料配置方式了. 如果想要新增飲品, 再弄一臺飲料機就行了.

來看看對應(yīng)關(guān)系

這是沒有標(biāo)簽的飲水機(飲料機):

public interface IBeverageMachine {

    Drink makeDrink();
}

這是貼了不同飲料類型的飲料機:

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();
    }
}

這是那些飲料(還是有一個抽象繼承關(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 "速溶可樂粉";
    }

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

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 "酸梅湯";
    }
}

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

現(xià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要橙汁時, 表妹去OrangeJuiceMachine裝一杯, 當(dāng)B需要可樂時, 表妹再去CokeMachine拿:

This is a cup of:橙汁
This is a cup of:可樂

表妹的工作變得更簡單了, 工作效率也更高了, 也更能微笑面對顧客了, 哈哈...

想要奶茶的C顧客

這天, 來了一位顧客D, 問: "老板, 有沒有熱奶茶啊?". 考驗小光的程序的時候到了. 很快, 小光copy出了一個奶茶機(擴展開放), 同時也無需修改原來的那些個飲料機程序(修改關(guān)閉), 不會因此而耽誤生意.

新增奶茶飲料:

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

奶茶機:

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

現(xiàn)在的臺面:


表妹的工作也很簡單, 去奶茶機那兒接奶茶就是了:

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

D拿到的:

This is a cup of:奶茶

故事之后

照例, 我們先來畫出現(xiàn)在的類對應(yīng)關(guān)系:

實際上這個就是工廠方法模式.


幾個點:

  • 1, 為何叫工廠方法, 是因為每個工廠有一個方法來創(chuàng)建產(chǎn)品.
  • 2, 每個產(chǎn)品對應(yīng)一個工廠實例來生產(chǎn)這個產(chǎn)品實例.
  • 3, 因為產(chǎn)品和其對應(yīng)的工廠都與其他產(chǎn)品分離, 我們可以很輕易的去增加新的產(chǎn)品和其對應(yīng)的工廠, 而不改變原來的結(jié)構(gòu). (開閉原則, 實際上還蘊含了職責(zé)單一)

擴展閱讀

工廠方法模式如同Buidler模式, 是一些開源庫中非常常見的用來創(chuàng)建實例的設(shè)計模式.

例如OkHttp中ModelLoader相關(guān)的實現(xiàn):


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

更多內(nèi)容撵幽,請關(guān)注菜鳥窩(微信公眾號ID: cniao5)莹弊,程序猿的在線學(xué)習(xí)平臺室梅。 轉(zhuǎn)載請注明出處臣咖,本文出自菜鳥窩婚苹,原文鏈接http://www.cniao5.com/forum/thread/8fb562da14e911e7be3e00163e0230fa

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市掌实,隨后出現(xiàn)的幾起案子矢否,更是在濱河造成了極大的恐慌,老刑警劉巖掏秩,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件或舞,死亡現(xiàn)場離奇詭異,居然都是意外死亡蒙幻,警方通過查閱死者的電腦和手機映凳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邮破,“玉大人诈豌,你說我怎么就攤上這事∈愫停” “怎么了矫渔?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長摧莽。 經(jīng)常有香客問我庙洼,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任油够,我火速辦了婚禮蚁袭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘石咬。我一直安慰自己揩悄,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布鬼悠。 她就那樣靜靜地躺著删性,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焕窝。 梳的紋絲不亂的頭發(fā)上蹬挺,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音它掂,去河邊找鬼汗侵。 笑死,一個胖子當(dāng)著我的面吹牛群发,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播发乔,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼熟妓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了栏尚?” 一聲冷哼從身側(cè)響起起愈,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎译仗,沒想到半個月后抬虽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡纵菌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年阐污,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咱圆。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡笛辟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出序苏,到底是詐尸還是另有隱情手幢,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布忱详,位于F島的核電站围来,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜监透,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一桶错、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧才漆,春花似錦牛曹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鸳玩,卻和暖如春阅虫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背不跟。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工颓帝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窝革。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓购城,卻偏偏與公主長得像,于是被迫代替她去往敵國和親虐译。 傳聞我的和親對象是個殘疾皇子瘪板,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

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