本系列文章由阿里大神
名俊
授權(quán)獨(dú)家發(fā)布
前情提要
本意是想像美劇的previously那樣, 不知道怎么翻譯好, 求翻譯達(dá)人賜教...
上集講到, 小光辭了工作, 開起了熱干面的店子, 用Builder模式改造了熱干面的構(gòu)建過程, 是日漸穩(wěn)定有效起來, 生意也是越來越好.
但是小光是善于觀察的同學(xué)啊, 他發(fā)現(xiàn)熱干面真的好干啊(好像一般人也都能發(fā)現(xiàn), 鬼臉~). 心想, 解決用戶痛點(diǎn)才產(chǎn)品的存在根本啊, 是時(shí)候推出新東西了.
于是他決定跟推出自己的光氏飲料產(chǎn)品.
飲料的制作
經(jīng)過一番調(diào)查和走訪, 小光發(fā)現(xiàn)幾個(gè)特點(diǎn):
大家對(duì)這個(gè)飲料要求不高(碼農(nóng)的屌絲特性啊) , 解渴為主.
因?yàn)橼s著上班, 一般要求要快, 最好可以直接拿走.
品種要豐富, 大家口味不一啊.
于是, 小光選用了最新的XX牌 (有廣告商找我嗎? 哈哈.) 速溶飲料. 制作飲料的過程很簡(jiǎn)單, 很快, 小光做出了第一杯飲料---橙汁:
public class OrangeJuice {
public void make() {
// 1. 拿出一次性飲料杯
System.out.println("拿出一次性飲料杯");
// 2. 加入速溶橙汁粉
System.out.println("加入速溶橙汁粉");
// 3. 加水沖兌
System.out.println("加水");
// 4. 加蓋, 打包
System.out.println("加蓋, 打包");
}
}
小光的思考
看起來, 程序似乎是可以運(yùn)轉(zhuǎn)了, 讓我們投入生產(chǎn)吧...
然而, 小光何許人啊, 畢竟是在碼農(nóng)界混了好些年的同志啊. 還沒有投入使用, 就發(fā)現(xiàn)了"問題":
飲料有很多種, 過程都類似, 只是放的速溶包不一樣. 如果我每個(gè)都這么寫, 改天真有人找我打廣告, 杯子上印個(gè)二維碼什么的, 我不是每個(gè)飲料的制作過程都要改啊
靈光一現(xiàn), 小光想起了面向?qū)ο笏枷胫刑岬降某橄? 封裝, 于是乎, 小光改寫了自己的程序:
他抽象出來一個(gè)"Drink"類:
public abstract class Drink {
public void make() {
// 1. 拿出一次性飲料杯
System.out.println("拿出一次性飲料杯");
// 2. 加入速溶橙汁粉
System.out.println("加入" + getInstantPackage());
// 3. 加水沖兌
System.out.println("加水");
// 4. 加蓋, 打包
System.out.println("加蓋, 打包");
}
abstract String getInstantPackage();
}
可樂, 酸梅湯, 橙汁皆繼承了Drink:
public class Coke extends Drink {
@Override
String getInstantPackage() {
return "速溶可樂粉";
}
}
public class PlumJuice extends Drink {
@Override
String getInstantPackage() {
return "速溶酸梅粉";
}
}
public class OrangeJuice extends Drink {
@Override
String getInstantPackage() {
return "速溶橙汁粉";
}
}
開賣
制作完飲料, 準(zhǔn)備開賣了, 是這樣的:
public class XiaoGuang {
public static void main(String[] args) {
OrangeJuice orangeJuice = new OrangeJuice();
orangeJuice.make();
}
}
第二天, 生意實(shí)在太好, 小光請(qǐng)了表妹臨時(shí)來幫忙泡制飲料. 而且, 小光還發(fā)現(xiàn)自己也無需關(guān)注用戶要什么飲料了, 直接讓用戶告訴表妹, 表妹直接制作飲料給用戶就行~
表妹負(fù)責(zé)根據(jù)用戶要求生產(chǎn)飲料:
public class Cousins {
public static Drink create(String drinkType) {
// Java7開始, switch支持String
switch (drinkType) {
case "橙汁":
return new OrangeJuice();
case "酸梅湯":
return new PlumJuice();
case "可樂":
return new Coke();
default:
return new OrangeJuice();
}
}
}
小光不再關(guān)注飲料具體種類:
public class XiaoGuang {
public static void main(String[] args) {
Drink drink = Cousins.create("可樂");
drink.make();
}
}
加上飲料套餐之后, 生意果然越來越好, 估計(jì)也有美女助陣的加成, 哈哈...
故事之后
可能有些同學(xué)已經(jīng)看出一點(diǎn)熟悉感了, 我們把這些關(guān)系一個(gè)UML表示下:
如此, 應(yīng)該就比較清晰了, 這個(gè)就是我們今天的主題---簡(jiǎn)單工廠.
嚴(yán)格來說, 簡(jiǎn)單工廠并非一種設(shè)計(jì)模式, 可以說是一種編碼習(xí)慣.
那么我們?yōu)槭裁匆褂煤?jiǎn)單工廠, 或者說這么做有什么好處呢?
從我們這個(gè)例子中, 可以看到, 小光(Client類)不需要去關(guān)注飲料泡制(Drink make)這個(gè)過程了, 有更多的時(shí)間去接待客戶, 只需從表妹(工廠類)那拿到相應(yīng)的飲料給客戶即可.
這個(gè)其實(shí)是蘊(yùn)含了單一職責(zé)的編程思想:
小光的職責(zé)是接待客戶
表妹的職責(zé)是泡制飲料
簡(jiǎn)單工廠一般來說, 使用一個(gè)靜態(tài)方法來生產(chǎn)產(chǎn)品, 故而有時(shí)也稱之為靜態(tài)工廠方法模式.
擴(kuò)展閱讀
在這個(gè)故事的過程中, 我們提到了面向?qū)ο蟮某橄? 封裝特性. 實(shí)際上我們所有的OOD原則, 設(shè)計(jì)模式, 都是基于面向?qū)ο蟮乃枷氲? 離不開抽象, 封裝, 繼承, 多態(tài)幾大特性. 隨著對(duì)這些設(shè)計(jì)模式的分析, 也可以讓我們加深面向?qū)ο蟮木幊趟枷?
以Glide為例, 其中的DefaultConnectivityMonitorFactory.java就是一個(gè)類似的簡(jiǎn)單工廠實(shí)現(xiàn):
public class DefaultConnectivityMonitorFactory implements ConnectivityMonitorFactory {
@NonNull
public ConnectivityMonitor build(
@NonNull
Context context,
@NonNull
ConnectivityMonitor.ConnectivityListener listener) {
final int res = context.checkCallingOrSelfPermission("android.permission.ACCESS_NETWORK_STATE");
final boolean hasPermission = res == PackageManager.PERMISSION_GRANTED;
if (hasPermission) {
return new DefaultConnectivityMonitor(context, listener);
} else {
return new NullConnectivityMonitor();
}
}
}
與表妹Cousins(工廠)的實(shí)現(xiàn)很類似, 只是這個(gè)Factory具體創(chuàng)建什么產(chǎn)品不是由傳入的參數(shù)決定的, 是在內(nèi)部的邏輯決定的.
轉(zhuǎn)化為類圖關(guān)系, 更加清晰:
一直在說的話: 所謂架構(gòu), 設(shè)計(jì)模式都是一種思想, 沒有固定的招式, 所有的這些招式都是讓我們?nèi)腴T, 了解面向?qū)ο蟮幕A(chǔ)思想, 然后能運(yùn)用無形. 共勉.
留個(gè)尾子
大家可能有發(fā)現(xiàn), 簡(jiǎn)單工廠的弊端也是很多的, 表妹(工廠)的責(zé)任太重, 包含(UML依賴關(guān)系)了所有的具體產(chǎn)品的實(shí)現(xiàn). 另外, 如果需要修改或增加產(chǎn)品, 我們就得改變工廠類的實(shí)現(xiàn). 這顯然違反了開閉原則.
故而, 簡(jiǎn)單工廠, 一般來說, 適用于產(chǎn)品類別較少, 且固定的場(chǎng)景.
更多內(nèi)容查剖,請(qǐng)關(guān)注菜鳥窩(微信公眾號(hào)ID: cniao5)辑畦,程序猿的在線學(xué)習(xí)平臺(tái)测砂。 轉(zhuǎn)載請(qǐng)注明出處征字,本文出自菜鳥窩,原文鏈接http://www.cniao5.com/forum/thread/604a659a102f11e790dc00163e0230fa