JS 設(shè)計(jì)模式之工廠模式

工廠模式

現(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)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冈在,一起剝皮案震驚了整個(gè)濱河市倒慧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌包券,老刑警劉巖纫谅,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異溅固,居然都是意外死亡付秕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)侍郭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)询吴,“玉大人,你說(shuō)我怎么就攤上這事亮元∶图疲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵爆捞,是天一觀的道長(zhǎng)奉瘤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)煮甥,這世上最難降的妖魔是什么盗温? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮成肘,結(jié)果婚禮上卖局,老公的妹妹穿的比我還像新娘。我一直安慰自己双霍,他們只是感情好砚偶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布批销。 她就那樣靜靜地躺著,像睡著了一般蟹演。 火紅的嫁衣襯著肌膚如雪风钻。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天酒请,我揣著相機(jī)與錄音骡技,去河邊找鬼。 笑死羞反,一個(gè)胖子當(dāng)著我的面吹牛布朦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播昼窗,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼是趴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了澄惊?” 一聲冷哼從身側(cè)響起唆途,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掸驱,沒(méi)想到半個(gè)月后肛搬,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毕贼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年温赔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鬼癣。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陶贼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出待秃,到底是詐尸還是另有隱情拜秧,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布章郁,位于F島的核電站腹纳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏驱犹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一足画、第九天 我趴在偏房一處隱蔽的房頂上張望雄驹。 院中可真熱鬧,春花似錦淹辞、人聲如沸医舆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蔬将。三九已至爷速,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霞怀,已是汗流浹背惫东。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毙石,地道東北人廉沮。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像徐矩,于是被迫代替她去往敵國(guó)和親滞时。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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