JS 设计模式之工厂模式

工厂模式

现实场景解读

插畫│綠野悠

首先我们构建这样一个场景,宝贝与妈妈,当宝贝想要商店里面的一样东西的时候,他是不能直接拿的,因为商品是需要付费的。

此时我们的妈妈就是我们宝宝的工厂提款机。宝宝想要好吃的,好玩的,他得向妈妈申请。妈妈是理性的,妈妈通常会判断该不该买这样东西。

比如说小孩生病了,不适合吃一些刺激性的事物,此时妈妈就会回绝宝宝的要求。

而且有的时候,宝宝太小,他有的时候没法说明具体想要什么,比如宝宝可能咿呀学语的说着:“糖糖”。而其实妈妈可能了解他的需求,他想要吃果冻了,所以妈妈就把果冻嚼碎喂给宝宝。

思考:

  • 宝宝不能直接拿商品,因为宝宝没有购买能力。

  • 对应着 ---- 我不想让谁都可以 new 某个对象,就像银行金卡只发行给资金量、信用级别都优秀的人。

  • 宝宝想要东西,得妈妈同意。

  • 对应着 ---- 在返回一个对象之前,我可以做一些校验逻辑,前置逻辑等。

  • 宝宝对应的需求描述不清楚,只有妈妈懂孩子,而且孩子吃果冻,妈妈会有一定的保护机制,嚼碎再给孩子吃。

  • 对应着 ---- 编写代码的人,可能要做一些危险操作,比如抛出异常,此时工厂会内部解决这个错误。

// 妈妈类
class Monther {
    // 向妈妈申请所有你想要的
    static giveMe(whatYouWant){
        switch(whatYouWant){
            // 糖糖
            case "tangtang":
                console.log("宝宝,你一个人吃果冻是非常危险的哦,妈妈喂你~~"); 
                return Month.chewJelly(new Jelly);
            // 飞飞
            case "feifei":
                console.log("宝宝,家里已经买了很多飞机了哦,")
                return null;
            default: return null;
        }
    }

    static chewJelly(jelly){
        jelly.chewed = true;
        return jelly;
    }
}

// 果冻类
class Jelly{
    // 是否咀嚼过的果冻
    chewed = false;
}

// 玩具飞机
class ToyPlane {}


// 宝宝要开始提需求了
// 宝宝要糖糖
let jelly = Monther.giveMe('tangtang');

// 宝宝要飞飞
let toyPlane = Monther.giveMe('feifei');

console.log(jelly instanceof Jelly ); // 妈妈给宝宝果冻
console.log(jelly.chewed === true ); // 宝宝得到的果冻是经过处理的
console.log(toyPlane === null) // 妈妈不同意买飞机

实际运用解读

使用过 Redux 开发 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':
            //这里只是简单处理
            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;
    }

};

此段代码来自于实例讲解基于 React+Redux 的前端开发流程

这段代码的作用就是,对原有的状态,和新的提交信息组合成一个新的状态。

注意: 返回的对象并不一定都是 new 出来的,也可以是 {} 这种字面量的形式。当然也没人规定一定要返回对象,你也可以返回你所需要的字符串、数字、正则等等。

我们传入了一些参数,或者说是需求给工厂,工厂根据我们的需求返回给我们所需的东西。

接下来,我们写一个可以运行的例子


// 正则工厂
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));

我们发现了一个规律,那就是工厂模式为了生产更多的东西,里面通常会用到 if 或者 switch 来进行判断。

其实仔细想一想,JS的模块何尝不是一种工厂呢?要什么就从模块里面申请什么。

对工厂模式再次进行抽象,工厂的工厂

现实场景解读

药丸
药丸
药丸
药丸

小朋友们一起玩过家家,这个过家家有2个流程,一个是把果实变成药瓶,而另一个是对药进行研磨混合。

对于大的厂商,它可能有很多个子产商,就比如手机行业的公司,它的一个分部公司专门为用户生产手机屏幕,而另外一个则专门用于生产手机电池。

思考:

  • 过家家和大的手机厂商厂

  • 对应着 ---- 对应着工厂的工厂。

  • 从工厂中得到工厂

  • 对应着 ---- 从过家家中得到其中一个流程,从大的手机厂商中得到专门生产手机屏幕的厂

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');

实例解读

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

我们就直接基于上面的例子进行,封装成一个新的工厂,尽管这2个工厂并不怎么搭调。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。 简...
    JSUED阅读 270评论 0 1
  • 关键词:函数,封装, 定义 把实现相同功能的代码放在一个函数中,以后想实现这个功能,只需要执行这个方法就行了-->...
    RomainLiu阅读 218评论 0 2
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,042评论 25 707
  • 再见,旧时光!(目录) 这个世界上,有千万种爱你的方式,可是我却选择了最决绝的一种。这样的我,你还喜欢吗? “二姐...
    w雨木阅读 422评论 0 2
  • 今天还是和往常一样5.50分起床,听课,下楼慢跑。因为有时外出,环境影响没有坚持运动,这周又接上去,感觉很累,心里...
    滴滴雨阅读 246评论 0 0