工廠模式
現(xiàn)實(shí)場(chǎng)景解讀
插畫(huà)│綠野悠
首先我們構(gòu)建這樣一個(gè)場(chǎng)景,寶貝與媽媽,當(dāng)寶貝想要商店里面的一樣?xùn)|西的時(shí)候赠法,他是不能直接拿的,因?yàn)樯唐肥切枰顿M(fèi)的乔夯。
此時(shí)我們的媽媽就是我們寶寶的工廠砖织,提款機(jī)。寶寶想要好吃的末荐,好玩的侧纯,他得向媽媽申請(qǐng)。媽媽是理性的甲脏,媽媽通常會(huì)判斷該不該買(mǎi)這樣?xùn)|西眶熬。
比如說(shuō)小孩生病了,不適合吃一些刺激性的事物块请,此時(shí)媽媽就會(huì)回絕寶寶的要求娜氏。
而且有的時(shí)候,寶寶太小墩新,他有的時(shí)候沒(méi)法說(shuō)明具體想要什么贸弥,比如寶寶可能咿呀學(xué)語(yǔ)的說(shuō)著:“糖糖”。而其實(shí)媽媽可能了解他的需求海渊,他想要吃果凍了绵疲,所以媽媽就把果凍嚼碎喂給寶寶。
思考:
寶寶不能直接拿商品切省,因?yàn)閷殞殯](méi)有購(gòu)買(mǎi)能力最岗。
對(duì)應(yīng)著 ---- 我不想讓誰(shuí)都可以 new 某個(gè)對(duì)象,就像銀行金卡只發(fā)行給資金量朝捆、信用級(jí)別都優(yōu)秀的人般渡。
寶寶想要東西,得媽媽同意。
對(duì)應(yīng)著 ---- 在返回一個(gè)對(duì)象之前驯用,我可以做一些校驗(yàn)邏輯脸秽,前置邏輯等。
寶寶對(duì)應(yīng)的需求描述不清楚蝴乔,只有媽媽懂孩子记餐,而且孩子吃果凍,媽媽會(huì)有一定的保護(hù)機(jī)制薇正,嚼碎再給孩子吃片酝。
對(duì)應(yīng)著 ---- 編寫(xiě)代碼的人,可能要做一些危險(xiǎn)操作挖腰,比如拋出異常雕沿,此時(shí)工廠會(huì)內(nèi)部解決這個(gè)錯(cuò)誤。
// 媽媽類
class Monther {
// 向媽媽申請(qǐng)所有你想要的
static giveMe(whatYouWant){
switch(whatYouWant){
// 糖糖
case "tangtang":
console.log("寶寶猴仑,你一個(gè)人吃果凍是非常危險(xiǎn)的哦审轮,媽媽喂你~~");
return Month.chewJelly(new Jelly);
// 飛飛
case "feifei":
console.log("寶寶,家里已經(jīng)買(mǎi)了很多飛機(jī)了哦辽俗,")
return null;
default: return null;
}
}
static chewJelly(jelly){
jelly.chewed = true;
return jelly;
}
}
// 果凍類
class Jelly{
// 是否咀嚼過(guò)的果凍
chewed = false;
}
// 玩具飛機(jī)
class ToyPlane {}
// 寶寶要開(kāi)始提需求了
// 寶寶要糖糖
let jelly = Monther.giveMe('tangtang');
// 寶寶要飛飛
let toyPlane = Monther.giveMe('feifei');
console.log(jelly instanceof Jelly ); // 媽媽給寶寶果凍
console.log(jelly.chewed === true ); // 寶寶得到的果凍是經(jīng)過(guò)處理的
console.log(toyPlane === null) // 媽媽不同意買(mǎi)飛機(jī)
實(shí)際運(yùn)用解讀
使用過(guò) Redux 開(kāi)發(fā) Reac t的朋友可能比較清楚 Reducer 疾渣。
export default (state = {
isPicking: false,
newAppleId: 1,
apples: [
{
id: 0,
weight: 235,
isEaten: false
}
]
}, action) => {
let newState ;
switch (action.type) {
case 'apple/BEGIN_PICK_APPLE':
newState = Object.assign({}, state, {
isPicking: true
});
return newState;
case 'apple/DONE_PICK_APPLE':
newState = Object.assign({}, state, {
apples: [
...state.apples,
{
id: state.newAppleId,
weight: action.payload,
isEaten: false
}
],
newAppleId: state.newAppleId + 1,
isPicking: false
})
return newState;
case 'apple/FAIL_PICK_APPLE':
//這里只是簡(jiǎn)單處理
newState = Object.assign({}, state, {
isPicking: false
});
return newState;
case 'apple/EAT_APPLE':
newState = Object.assign({}, state, {
apples: [
...state.apples.slice(0, action.payload),
Object.assign({}, state.apples[action.payload], { isEaten: true }),
...state.apples.slice(action.payload + 1)
]
})
return newState;
default:
return state;
}
};
此段代碼來(lái)自于實(shí)例講解基于 React+Redux 的前端開(kāi)發(fā)流程
這段代碼的作用就是,對(duì)原有的狀態(tài)崖飘,和新的提交信息組合成一個(gè)新的狀態(tài)榴捡。
注意: 返回的對(duì)象并不一定都是 new 出來(lái)的,也可以是 {} 這種字面量的形式朱浴。當(dāng)然也沒(méi)人規(guī)定一定要返回對(duì)象薄疚,你也可以返回你所需要的字符串、數(shù)字赊琳、正則等等。
我們傳入了一些參數(shù)砰碴,或者說(shuō)是需求給工廠躏筏,工廠根據(jù)我們的需求返回給我們所需的東西。
接下來(lái)呈枉,我們寫(xiě)一個(gè)可以運(yùn)行的例子
// 正則工廠
function fieldTest(fieldName){
switch(fieldName){
case 'phone':
return /^1[3|4|5|8][0-9]\d{4,8}$/;
case 'email':
return /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
case 'character': // 是否為漢字
return /^[\u4e00-\u9fa5]{0,}$/;
}
}
let email = 'belovedyogurt@gmail.com';
let name = "陳大明";
console.log(fieldTest('email').test(email));
console.log(fieldTest('character').test(name));
我們發(fā)現(xiàn)了一個(gè)規(guī)律趁尼,那就是工廠模式為了生產(chǎn)更多的東西,里面通常會(huì)用到 if 或者 switch 來(lái)進(jìn)行判斷猖辫。
其實(shí)仔細(xì)想一想酥泞,JS的模塊何嘗不是一種工廠呢?要什么就從模塊里面申請(qǐng)什么啃憎。
對(duì)工廠模式再次進(jìn)行抽象芝囤,工廠的工廠
現(xiàn)實(shí)場(chǎng)景解讀
小朋友們一起玩過(guò)家家,這個(gè)過(guò)家家有2個(gè)流程,一個(gè)是把果實(shí)變成藥瓶悯姊,而另一個(gè)是對(duì)藥進(jìn)行研磨混合羡藐。
對(duì)于大的廠商,它可能有很多個(gè)子產(chǎn)商悯许,就比如手機(jī)行業(yè)的公司仆嗦,它的一個(gè)分部公司專門(mén)為用戶生產(chǎn)手機(jī)屏幕,而另外一個(gè)則專門(mén)用于生產(chǎn)手機(jī)電池先壕。
思考:
過(guò)家家和大的手機(jī)廠商廠
對(duì)應(yīng)著 ---- 對(duì)應(yīng)著工廠的工廠瘩扼。
從工廠中得到工廠
對(duì)應(yīng)著 ---- 從過(guò)家家中得到其中一個(gè)流程,從大的手機(jī)廠商中得到專門(mén)生產(chǎn)手機(jī)屏幕的廠
function XiaoMi(factoryName) {
switch(factoryName){
case 'battery': return MobileBatteryFactory;
case 'screen': return MobileScreenFactory;
}
}
class Battery{};
class MobileBatteryFactory {
static getBattery(){
return new Battery();
}
}
class MobileScreenFactory {
static getScreen(){
return { name: 'screen' }
}
}
console.log(XiaoMi('battery').getBattery() instanceof Battery);
console.log(XiaoMi('screen').getScreen().name === 'screen');
實(shí)例解讀
class AllFactory {
static getFieldTest = () => fieldTest;
static getMother = () => Mother
}
let mom = AllFactory.getMother();
let test = AllFactory.getFieldTest();
console.log(mom === Mother);
console.log(test('email').test(email));
我們就直接基于上面的例子進(jìn)行垃僚,封裝成一個(gè)新的工廠集绰,盡管這2個(gè)工廠并不怎么搭調(diào)。