美文网首页
JS 设计模式之工厂模式

JS 设计模式之工厂模式

作者: Nodelover | 来源:发表于2017-03-04 17:02 被阅读424次

工厂模式

现实场景解读

插畫│綠野悠

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

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

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

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

思考:

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

  • 对应着 ---- 我不想让谁都可以 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个工厂并不怎么搭调。

相关文章

  • 前端设计模式

    JS设计模式一:工厂模式jS设计模式二:单例模式JS设计模式三:模块模式JS设计模式四:代理模式JS设计模式五:职...

  • iOS设计模式(三)之抽象工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(一)之简单工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(二)之工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式之美-适配器模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • iOS设计模式之美-抽象工厂模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • iOS设计模式之美-工厂模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • iOS设计模式之美-生成器模式

    iOS设计模式之美-工厂模式iOS设计模式之美-抽象工厂模式iOS设计模式之美-生成器模式iOS设计模式之美-适配...

  • 设计模式之工厂模式

    设计模式之工厂模式 标签(空格分隔): 设计模式 工厂模式 设计模式的感念 设计模式的应用 工厂设计模式的产生 工...

  • 设计模式系列

    创建型模式: 设计模式之工厂模式(Factory Pattern)设计模式之抽象工厂模式(Abstract Fac...

网友评论

      本文标题:JS 设计模式之工厂模式

      本文链接:https://www.haomeiwen.com/subject/ljrjgttx.html