工厂模式
现实场景解读
插畫│綠野悠
首先我们构建这样一个场景,宝贝与妈妈,当宝贝想要商店里面的一样东西的时候,他是不能直接拿的,因为商品是需要付费的。
此时我们的妈妈就是我们宝宝的工厂,提款机。宝宝想要好吃的,好玩的,他得向妈妈申请。妈妈是理性的,妈妈通常会判断该不该买这样东西。
比如说小孩生病了,不适合吃一些刺激性的事物,此时妈妈就会回绝宝宝的要求。
而且有的时候,宝宝太小,他有的时候没法说明具体想要什么,比如宝宝可能咿呀学语的说着:“糖糖”。而其实妈妈可能了解他的需求,他想要吃果冻了,所以妈妈就把果冻嚼碎喂给宝宝。
思考:
-
宝宝不能直接拿商品,因为宝宝没有购买能力。
-
对应着 ---- 我不想让谁都可以 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个工厂并不怎么搭调。
网友评论