JavaScript-设计模式(二) 工厂模式
工厂模式定义:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
分类:简单工厂模式 、工厂方法模式
目的:工厂模式的目的是为了实现解耦,将对象的创建和使用分开,即应用程序将对象的创建和初始化职责交给工厂对象。
作用:
1.降低代码重复。由于创建过程都由工厂统一的管理,有利于当业务发生变化之后的修改
2.工厂模式将创建和使用分离,使用者不需要知道具体的创建过程,只需要使用即可。
3.类本身有很多子类,并且经常性发生变化。
4.提高代码的可维护性
使用场景:
//1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 //2、Hibernate 换数据库只需换方言和驱动就可以。
实现一个简单工厂模式:
function Person(n,a) {
this.name = n
this.age = a
}
let a = new Person("麻子",18)
console.log(a);
工厂方法模式: (使创建过程延迟早子类进行)
//烧烤
class Grill{
constructor(){
this.price = 20
this.time = 15
}
done(){
console.log(`Grill搞定了,价格${this.price},耗时${this.time}分钟`);
}
}
//面条
class Noodles{
constructor(){
this.price = 20
this.time = 15
}
done(){
console.log(` Noodles搞定了,价格${this.price},耗时${this.time}分钟`);
}
}
//牛排
class Steak{
constructor(){
this.price = 50
this.time = 20
}
done(){
console.log(`Steak搞定了,价格${this.price},耗时${this.time}分钟`);
}
}
//开放一个对外的窗口
function shop(name){
let goods = null
switch(name){
case "Steak":
goods = new Steak()
break
case "Noodles":
goods = new Noodles()
break
case "Grill":
goods = new Grill()
break
}
return goods
}
let a = shop("Steak");
let b = shop("Noodles");
let c = shop("Grill");
a.done()
b.done()
c.done()
此时代码还是比较分散 需要我们进一步改进 便于维护,如下:
//开放一个对外的窗口
function shop(name) {
// 原材料
let goods = null
//烧烤
class Grill {
constructor() {
this.price = 20
this.time = 15
}
done() {
console.log(`Grill制作完成,价格${this.price},耗时${this.time}分钟`);
}
}
//面条
class Noodles {
constructor() {
this.price = 20
this.time = 15
}
done() {
console.log(`Noodles制作完成,价格${this.price},耗时${this.time}分钟`);
}
}
//牛排
class Steak {
constructor() {
this.price = 50
this.time = 20
}
done() {
console.log(`Steak制作完成,价格${this.price},耗时${this.time}分钟`);
}
}
//米饭
class Rice{
constructor(){
this.price = 10
this.time = 10
}
done() {
console.log(`Rice制作完成,价格${this.price},耗时${this.time}分钟`);
}
}
// 对原材料进行加工
switch (name) {
case "Steak":
goods = new Steak()
break
case "Noodles":
goods = new Noodles()
break
case "Grill":
goods = new Grill()
break
case "Rice":
goods = new Rice()
break
}
// 出厂
return goods
}
let a = shop("Steak");
let b = shop("Noodles");
let c = shop("Grill");
let d = shop("Rice");
a.done()
b.done()
c.done()
d.done()
此时虽然我们将代码逻辑进行了一个集中,但是同样面临一个问题,当我们需要新增一些工厂类的时候,需要在工厂函数中创建类实例并且,需要加case,很麻烦。如果逻辑比较复杂 ,代码会变得比较臃肿
//先来看一下 无共性的代码
//开放一个对外的窗口
let Shop = (function () {
const SHOP = {
//无共性
a: class {
constructor() {
this.a = 1
this.b = 2
}
},
b: class {
constructor() {
this.aa = 1
this.bb = 2
}
},
c: class {
constructor() {
}
log() {
console.log("sb");
}
},
d: class {
constructor() {
this.a = 666
}
}
}
return class {
constructor(n) {
return new SHOP[n]()
}
}
})()
let a = new Shop("a");
let b = new Shop("b");
let c = new Shop("c");
let d = new Shop("d");
console.log(a);
console.log(b);
console.log(c);
console.log(d);
// 当代码具有共性 我们需要提取公共的部分
let Shop = (function () {
const SHOP = {
Grill() {
this.price = 20
this.time = 15
},
Steak() {
this.price = 50
this.time = 20
},
Noodles() {
this.price = 15
this.time = 5
},
//新增产品 只需要修改这一步
Rice() {
this.price = 10
this.time = 5
}
}
return class {
constructor(name) {
this.name = name
if (SHOP[name]) {
SHOP[name].call(this) //将SHOP的this指向当前实例的this
} else {
// 处理报错的情况
throw new Error("需要的餐品不存在")
}
}
// 公共部分 相同
done() {
console.log(`${this.name}制作完成,价格${this.price},耗时${this.time}分钟`);
}
}
})()
let a = new Shop("Steak")
let b = new Shop("Grill")
let c = new Shop("Noodles")
let d = new Shop("Rice")
a.done()
b.done()
c.done()
d.done()
这个时候 后续每次新增只需要在SHOP工厂类中增加对应的属性就行了,而无需书写额外的代码,提高了代码的维护性。
如果需要给工厂类中增加一些没有共性的,可以增加一个参数,用来控制是否具有共性,从而执行后续的产出代码~
let Shop = (function () {//自调用函数 返回值决定其类型
const SHOP = {
//有共性
Grill() {
this.price = 20
this.time = 15
},
Steak() {
this.price = 50
this.time = 20
},
Noodles() {
this.price = 15
this.time = 5
},
//新增产品 只需要修改这一步
Rice() {
this.price = 10
this.time = 5
},
//新增一个没有共性的
Goudan: class {
constructor() {
this.name = "狗蛋"
this.age = 18
}
aa() {
console.log(11);
}
bb() {
console.log(22);
}
}
}
return class {//产出
constructor(n, mode) {
if (mode) return new SHOP[n]()//对于新增的没有共性的方法 将在 这里导出
this.name = n
if (SHOP[n]) {
SHOP[n].call(this)//将SHOP的this指向这个this
} else {
throw new Error("需要的餐品不存在")
}
}
done() {
console.log(`${this.name}制作完成,价格${this.price},耗时${this.time}分钟`);
}
}
}
)()
let a = new Shop("Steak")
let b = new Shop("Grill")
let c = new Shop("Noodles")
let d = new Shop("Rice")
let f = new Shop("Goudan", true)
a.done()
b.done()
c.done()
d.done()