一个例子搞懂设计模式之工厂模式
需求:弹窗需求,弹窗类型有多种,有不同的样式和内容。
比如有三个构造函数分别是消息弹窗,确认弹窗和取消弹窗的
function infoPop(){}
function confirmPop(){}
function cancelPop(){}
常规做法,根据不同的需求,创建不同的实例
// 创建2个消息弹窗,2个确认弹窗,2个取消弹窗
// 常规做法
new infoPop('welcome','red')
new infoPop('hello','blue')
new confirmPop('success','green')
采用工厂模式:
function pop(type,content,style){
switch(type){
case 'infoPop':
return new infoPop(content,style)
case 'confirmPop':
return new confirmPop(content,style)
case 'cancelPop':
return new cancelPop(content,style)
}
}
分析: 不够健壮,如果用户不是直接调用pop,而是通过new 的方法调用pop,就会出现问题。
1我们先判断用户是否是new调用的,做相应的处理。 如果是new调用的,那么this 的instanceof是pop,我们就手动new 调用对应的构造函数。
如果不是通过new调用的,我们转为new调用该函数。
2不需要switch-case去判断,而是挂载到原型上去。这样以后如果添加方法,直接在原型上添加即可,不需要再去维护判断语句
3 把pop函数挂载到window上去 优化后的代码:
(function(){
function pop(type,content,style){
pop.prototype.infoPop = function(content,style){
console.log(`infoPop-${content}:${style}`)
}
pop.prototype.confirmPop = function(content,style){
console.log(`confirmPop-${content}:${style}`)
}
pop.prototype.cancelPop = function(content,style){
console.log(`cancelPop-${content}:${style}`)
}
if(this instanceof pop){
return new this[type](content,style)
}else{
return new pop(type,content,style)
}
}
window.pop = pop
})()
这样,外部只需要调用我的工厂函数即可,而不用关心我要具体用哪个构造函数去new实例化一个对象。
let pops = [
{type:'infoPop',content:'hello',style:'red'},
{type:'infoPop',content:'welcome',style:'green'},
{type:'cancelPop',content:'取消',style:'yellow'},
{type:'cancelPop',content:'确定取消',style:'blue'},
{type:'confirmPop',content:'确定?',style:'green'},
{type:'confirmPop',content:'ok',style:'green'},
]
pops.forEach(item=>{
let {type,content,style} = item
pop(type,content,style)
})