「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
构造器模式
构造器模式可以用来处理创建多个相同属性的对象。
function Person(name,age){
this.name = name
this.age = age
}
let An = new Person('安',22)
let Qyt = new Person('权',22)
构造器模式可以用来处理创建多个相同属性的对象。
但是如果需要根据职业进行区分呢,还是可以用构造器解决。
但是就需要多个构造器了,比如前端开发,技术支持,产品经理等等
function FrontEnd(name,age){
this.name = name
this.age = age
this.career = '前端开发'
}
function TechnicalSupport(name,age){
this.name = name
this.age = age
this.career = '技术支持'
}
然后再创建一个函数,将变化的职业交给switch去处理,这样就算的上是简单工厂模式。
简单工厂模式
将对象的公用属性抽离到一个构造函数中,通过构造函数配合switch实现返回不同的对象。
function Factory(name,age,career){
switch (career) {
case 'FrontEnd':
return FrontEnd(name,age)
break
case 'TechnicalSupport':
return TechnicalSupport(name,age)
break
...
}
}
let An = Factory('安',22, 'FrontEnd')
let Qyt = Factory('权',22, 'TechnicalSupport')
但是这样会有一个问题,就是有很多工种的话就要单独写很多构造函数,找到两个构造函数的共性,抽离到一个构造函数中。
function worker(name,age,career,work){
this.name = name
this.age = age
this.career = career
this.work = work
}
function Factory(name,age,career){
let work
switch (career) {
case 'FrontEnd':
work = ['写代码','改bug']
break
case 'TechnicalSupport':
work = ['沟通甲方','让程序员改bug']
break
default:
work = null
}
return worker(name,age,career,work)
}
这样就可以无脑传参了,每次添加新职业只需要新增一条case就行了。
对于简单工厂的思考
以下对于简单工厂模式所想到的应用。
Redux中的action和reducer
action中通过构造函数创建不同的action
在reducer中通过判断payload来决定返回不同的state
抽象工厂
在实际业务中,复杂度可能并不是几个类或一个工厂可以解决,而是需要多个工厂。
比如之前的例子,worker代表打工人,假如还有Boss呢?Boss有更多的权限,有比worker更多的属性。如果在工厂函数中针对Boss去修改,就违反了开放封闭原则-软件实体(类、模块、函数)可以扩展,但是不可修改。抽象工厂可以解决这样的问题。
什么是抽象工厂?
拿小米手机举例
// 手机工厂
class Phone {
createPhone() {
throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
}
}
// 小米手机工厂
class MiPhone extends Phone{
createPhone() {
return new xiaomi()
}
}
// 抽象产品类-系统
class OS {
showOS() {
throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
}
}
// 系统的具体产品类
class xiaomi extends OS {
showOS() {
console.log('MIUI')
}
}
let Mi12 = new MiPhone().createPhone()
Mi12.showOS() // MIUI
首先是手机工厂,也就是根据手机抽象出来的共性,根据共性去拓展(extends),就产生了小米手机工厂。
其次是系统工厂(手机必须得有系统才行),也就是根据手机系统抽象出来的共性,可以拓展出具体的MIUI系统。
如果这个工厂此时还需要给苹果生产手机该怎么做呢?就仅需要对于手机工厂拓展一个新类叫苹果手机工厂,而对于OS拓展一个新的类apple就可以了,这样就实现了拓展但不修改,不会违反开放封闭原则了。
class IPhone extends Phone{
createPhone() {
return new apple()
}
}
class apple extends OS {
showOS() {
console.log('IOS')
}
}
let IPhone13 = new IPhone().createPhone()
IPhone13.showOS() //IOS
抽象工厂总结
抽象工厂主要有四个关键角色。
- 抽象工厂(抽象类):用于声明目标产品的共性,对应到上面的例子就是Phone类。
- 具体工厂(用于生产具体的产品):继承于抽象工厂,实现了抽象工厂声明的方法,用于创建具体的产品。比如MiPhone, IPhone…
- 抽象产品(抽象类下的产品的共性):具体工厂中的接口会依赖一些类,也就是一些更细节的东西。比如对于手机而言,就是系统、芯片等…
- 具体产品(抽象产品的具体产品):拿操作系统来说,比如有MIUI、IOS等。
定义就是围绕着一个超级工厂创建其他工厂,在JS世界中应用并不广泛,但应当了解。()
总结
一个对象时使用构造模式(构造函数)、多个对象(有共性,不同点只有一个)时使用简单工厂(工厂函数)、多种对象(有共性,但多个属性都各不相同或需要拓展性)时使用抽象工厂。