什么是工厂模式?
工厂模式就是将创建对象的过程单独封装。它像一条生产线,你告诉工厂需要什么样的产品,工厂就负责按照规格生产出来。
工厂模式的类型
1. 简单工厂模式
基本概念
简单工厂是最基础的工厂模式,通过一个 工厂类 根据传入的参数创建不同的对象。
想象一下,你在开发一个系统界面,需要一些按钮组件。这时你不需要自己去写每个按钮的具体实现,而是告诉按钮工厂:"我需要一个Windows风格的按钮",工厂ButtonFactory
就会给你返回一个符合要求的按钮组件。
代码实现
// 基础按钮类
class Button {
constructor(theme) {
this.theme = theme;
}
render() {
return `渲染一个普通按钮`;
}
}
// Windows风格按钮
class WindowsButton extends Button {
render() {
return `渲染一个 Windows 风格的按钮`;
}
}
// Mac风格按钮
class MacButton extends Button {
render() {
return `渲染一个 Mac 风格的按钮`;
}
}
// 按钮工厂:专注于单一职责 - 创建按钮
class ButtonFactory {
static createButton(theme) {
switch(theme) {
case 'windows':
return new WindowsButton(theme);
case 'mac':
return new MacButton(theme);
default:
return new Button(theme);
}
}
}
使用示例
const windowsBtn = ButtonFactory.createButton('windows');
console.log(windowsBtn.render()); // 输出:渲染一个 Windows 风格的按钮
2. 从简单工厂到抽象工厂的演进
简单工厂的局限性
随着业务的发展,我们发现单一的按钮工厂已经不能满足需求了。想象一下,你正在开发一个完整的系统界面:
- 最初,你只需要创建按钮,使用简单工厂就足够了
- 但很快,你发现需要创建更多的UI组件:
- 按钮(Button)
- 输入框(Input)
- 下拉菜单(Select)
- 对话框(Dialog) ...等等
更重要的是,这些组件必须保持统一的设计风格。比如当你选择了Windows风格,所有组件都应该是Windows风格的。这就好比你在开发一个完整的UI组件库,而不是零散地生产单个组件。
这时候,我们需要一个更强大的工厂系统,它能够:
- 统一管理多种类型的UI组件
- 确保所有组件风格的一致性
- 方便未来扩展新的组件类型
这就是抽象工厂模式诞生的背景。
3、抽象工厂模式
抽象工厂模式会提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
这句话猛然之间好像不太好理解,你就记住抽象工厂(AbstractFactory)是用来定规矩的,抽象工厂不干活,具体工厂(ConcreteFactory)来干活!
当你需要一套特定风格(比如Windows风格)的UI组件时,抽象工厂会确保为你创建的所有组件(按钮、输入框等)都保持相同的设计风格。
// 抽象工厂:定义创建产品的标准接口
class UIFactory {
createButton() {
throw new Error('必须实现createButton方法');
}
createInput() {
throw new Error('必须实现createInput方法');
}
}
// Windows风格工厂
class WindowsUIFactory extends UIFactory {
createButton() {
return new WindowsButton();
}
createInput() {
return new WindowsInput();
}
}
// 使用示例
const windowsFactory = new WindowsUIFactory();
const button = windowsFactory.createButton(); // 正常工作
const input = windowsFactory.createInput(); // 正常工作
// 错误的使用方式
const baseFactory = new UIFactory();
baseFactory.createButton(); // 错误:必须实现createButton方法
在基类
UIFactory
中,createButton
和createInput
是一个抽象方法,这种设计相当于在说:"这个方法必须被子类重写,不能直接使用父类的方法",工厂方法模式的核心就是让子类决定具体要创建什么类型(风格)的对象。如果子类不实现这个方法,整个模式的目的就无法达成,种设计确保了工厂方法模式的完整性,防止了半成品工厂的产生。
假如有一天,Windows风格的产品过气了,我们需要产出一款新风格UI投入市场,这时候怎么办?我们不需要对抽象工厂UIFactory
做任何修改,只需要拓展它的种类:
// Mac风格工厂
class MacUIFactory extends UIFactory {
createButton() {
return new MacButton();
}
createInput() {
return new MacInput();
}
}
这个操作对原有的产品风格不会造成任何潜在影响 ,遵守开放封闭原则 ——— “对拓展开放,对修改封闭”。
两种类型的对比
简单工厂
- 优点:实现简单,使用方便
- 缺点:扩展性差,不适合创建相关产品族
- 适用场景 :产品种类较少且相对稳定
抽象工厂
- 优点:可以创建产品族,扩展性好
- 缺点:类的数量增多,结构相对复杂
- 适用场景 :需要创建一系列相关产品
总结
工厂模式的演进过程反映了软件设计中一个重要的原则: 从简单到复杂,从具体到抽象 。当简单工厂无法满足需求时,我们就需要考虑使用抽象工厂来处理更复杂的对象创建场景。选择哪种模式,关键是要根据实际业务需求和未来可能的变化来决定。好的设计模式应该能够帮助我们写出更加优雅、可维护的代码。