什么是工厂模式?
一种创建型设计模式,通过一种统一的接口来创建对象的实例,不需要指定具体的类,隐藏了对象的创建过程,使得客户端代码不需要知道实际创建的对象是哪个类的实例;通常涉及定义一个接口或基类,然后实现该接口或派生类,最后通过一个工厂类来创建对象实例。这样可以使客户端代码从具体的类实现中解耦,只需依赖于接口或基类。
有两种主要的工厂模式:
-
简单工厂模式: 通过一个工厂类来创建不同类型的对象,客户端只需要知道工厂类和产品的接口。
-
工厂方法模式: 将对象的创建延迟到子类,每个子类实现工厂接口以创建具体的对象,客户端通过与工厂接口交互,而不是直接与具体类交互。
业务场景:
-
对象创建复杂度高: 当对象的创建过程比较复杂或涉及多个步骤时,工厂模式可以封装这些复杂性,提供一个简洁的接口供客户端使用。
-
对象的创建需要满足某些条件: 如果对象的创建依赖于一些条件或参数,工厂模式可以根据这些条件动态地创建对象,而无需客户端了解具体的创建过程。
-
类的具体实现可能经常变化: 当系统中的类的具体实现可能经常变化,而客户端只关心对象的接口时,工厂模式可以隐藏这些实现细节,降低客户端的耦合度。
-
避免直接使用构造函数实例化对象: 直接使用构造函数实例化对象可能使代码依赖于具体的类,而工厂模式可以将对象的创建逻辑集中在一个地方,更容易进行维护和修改。
-
实现产品族的统一管理: 当存在一组相关或相互依赖的对象时,工厂模式可以确保这些对象之间的一致性,例如创建具有相同主题或样式的 UI 组件。
假如有一个可以绘制相应图形的工厂:
1、未使用工厂模式
// 未使用工厂模式的代码
class Circle {
draw() {
console.log('Drawing a circle');
}
}
class Square {
draw() {
console.log('Drawing a square');
}
}
// 客户端代码
const circle = new Circle();
const square = new Square();
circle.draw(); // 输出: Drawing a circle
square.draw(); // 输出: Drawing a squared
代码中存在几个问题:
1)、客户端需要知道具体的类实现,会导致代码的耦合度比较高
2)、如果需要新增其他形状,客户端的代码需要进行修改
2、使用工厂模式改进一下
// 使用简单工厂模式的代码
class ShapeFactory {
createShape(type) {
switch (type) {
case 'circle':
return new Circle();
case 'square':
return new Square();
default:
throw new Error('请联系工厂制作新的模型');
}
}
}
class Circle {
draw() {
console.log('Drawing a circle');
}
}
class Square {
draw() {
console.log('Drawing a square');
}
}
// 客户端代码
const shapeFactory = new ShapeFactory();
const circle = shapeFactory.createShape('circle');
const square = shapeFactory.createShape('square');
circle.draw(); // 输出: Drawing a circle
square.draw(); // 输出: Drawing a square
使用简单工厂模式后,客户端不再直接依赖于具体的类,而是通过工厂类创建对象,提高了代码的灵活性和可维护性。新增形状只需修改工厂类而不影响客户端代码。