「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」
在学习中有这样一段话:在学一样东西的时候,可以按照它是什么,有什么用,优点是什么,缺点是什么,要怎么去使用,或者使用的时候要注意什么。我觉得这五部曲还是很有用的,能帮你快速掌握一个知识点
前言
昨天我们介绍了简单工厂模式,提到了简单工厂模式存在的问题:
- 违背了 开闭原则 ,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。
- 简单工厂模式由于使用了 static 方法,不能被继承和重写,这样就没有办法通过继承来形成一个阶级结构。
工厂方法模式的出现,就是为了解决这个问题,对简单工厂模式进一步抽象化,使其可以在不修改原来代码的情况下引进新的产品,也就是满足了开闭原则。
工厂方法模式是什么
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
简单的来说,就是将类的实例化也就是之前的创建产品,不再交给工厂类来实现,而是定义子类来决定实例化哪一个类,也就是创建哪种产品。
将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。
工厂方法模式的优点
- 灵活性增强 。对于添加新产品的过程就是新增工厂子类而不是修改工厂逻辑,符合 开闭原则。
- 解耦 。不再是由工厂类负责所以产品的创建,而是由工厂给出接口,子类来进行创建。
工厂方法模式的缺点
- 系统复杂度提升。类的个数容易过多,增加了系统的复杂程度。
- 只能产生一种品种的产品。抽象类只能产生一种类型的产品,多个类型将会有多个抽象类,这个弊端会在 抽象工厂模式 解决。
工厂方法模式的使用
工厂方法模式的本意是将实际创建对象的工作推迟到子类中,这样核心类就变成了抽象类。但是在js中并不存在抽象类的创建方式,所以我们只能是模仿核心思想。并且在实例化的过程当中,我们可以通过 new.target 来防止工厂类被实例化。
class Card {
constructor(opt) {
if (new.target === Card) {
throw new Error("抽象类不能被实例化");
}
this.name = (opt && opt.name) || "";
this.calculate = (opt && opt.calculate) || null;
}
}
class CardFactory extends Card {
constructor(name, calculate) {
super(name, calculate);
}
getInstance(role) {
switch (role) {
case "common":
return new CardFactory({
name: "普通会员",
calculate: (price) => {
return price * 0.9;
},
});
break;
case "sliver":
return new CardFactory({
name: "白银会员",
calculate: (price) => {
return price * 0.8;
},
});
break;
case "glod":
return new CardFactory({
name: "黄金会员",
calculate: (price) => {
return price * 0.7;
},
});
break;
default:
throw new Error("参数错误, 可选参数:common, sliver, glod");
}
}
}
let cardFactory = new CardFactory();
let common = cardFactory.getInstance("common");
console.log(common.calculate(100));
let sliver = cardFactory.getInstance("sliver");
console.log(sliver.calculate(100));
let glod = cardFactory.getInstance("glod");
console.log(glod.calculate(100));
但是要注意,最开始创建工厂方法的时候,是没有存入对应的参数的,所以在父类中要做对应的判断防止报错。剩下的就是和简单工厂模式差不多的使用,不同的实例会调用他们自己的方法返回不同的结果。
以上就是一个简单的工厂方法模式,可以看出来比起之前的简单工厂模式,工厂方法模式将这一过程进行了相对的解耦,更加符合设计原则。
总结
工厂方法模式 解决了 简单工厂模式 带来的部分问题,但是也存在着部分问题,在之后会有 抽象工厂模式 来解决 工厂方法模式 的部分缺点,后续会继续降到它是如果解决的,做出了什么样子的优化。