zhangdizhangdi

工厂模式 ⭐

定义

工厂模式(Factory Pattern):把“创建对象”这件事单独封装起来。
提供一种隐藏创建逻辑的对象创建方式,而不是通过直接 new 暴露实例化过程。

应用场景

  • jQuery $
  • React.createElement
  • Vue render
  • UI 组件库
  • 动态表单

核心对比

简单工厂解决“创建问题”,工厂方法解决“扩展问题”,抽象工厂解决“产品族问题”。

模式 解决的核心问题 特点 / 痛点 前端常见场景
简单工厂 new 对象的过程封装起来。 只有一个万能工厂类。违背开闭原则,修改逻辑需改核心代码。 根据后端返回的 type 字段渲染不同的图表(Line, Bar, Pie)。
工厂方法 解决简单工厂违背开闭原则的问题。 把大工厂拆成无数小工厂(一类产品配一个工厂)。扩展性好,但类容易爆炸。 复杂框架的底层设计,如 Vue/React 源码中的不同节点的创建工厂。
抽象工厂 解决**“系列产品(产品族)”**的一致性创建问题。 一次性产出一整套具有相关性的产品。避免风格或环境不匹配。 暗黑/明亮主题组件库;小程序/H5跨平台多端 API 适配层。

简单工厂模式

建立一个专门的工厂类,里面包含一个大大的 if-else 或 switch。调用者只需传入一个参数(如产品名字),工厂就能帮你生产出对应的实例。
❌ 严重违背“开闭原则”(OCP)

js
// 基础产品类
class SuccessAlert { show() { console.log("显示成功绿色弹窗"); } }
class ErrorAlert { show() { console.log("显示失败红色弹窗"); } }

// 简单工厂类
class AlertFactory {
  // 核心就是一个静态方法,根据参数返回不同对象
  static createAlert(type) {
    switch (type) {
      case 'success':
        return new SuccessAlert();
      case 'error':
        return new ErrorAlert();
      default:
        throw new Error("没这个类型的弹窗!");
    }
  }
}

// 业务调用(我不管你怎么new的,我只要个成功的弹窗)
const myAlert = AlertFactory.createAlert('success');
myAlert.show();

工厂方法模式 ⭐

定义

工厂方法模式(Factory Method Pattern),本意是将实际创建对象的工作推迟到子类中,这样核心类就变成了抽象类。
我们可以将工厂方法看作是一个实例化对象的工厂类。
✅ 完美符合“开闭原则”。

实现

ts
// 1. 抽象产品
interface IAlert { show(): void; }
// 2. 具体产品
class SuccessAlert implements IAlert { show() { console.log("成功弹窗"); } }
class ErrorAlert implements IAlert { show() { console.log("错误弹窗"); } }

// 3. 抽象工厂(核心:定义了造产品的规范,但不具体造)
interface IAlertFactory {
  createAlert(): IAlert;
}

// 4. 具体工厂(一种产品对应一个工厂)
class SuccessAlertFactory implements IAlertFactory {
  createAlert() { return new SuccessAlert(); }
}
class ErrorAlertFactory implements IAlertFactory {
  createAlert() { return new ErrorAlert(); }
}

// 业务调用
// 假设这是成功的业务逻辑,我引入专门生产Success的工厂
const factory = new SuccessAlertFactory(); 
const alert = factory.createAlert();
alert.show();

抽象工厂模式

定义

抽象工厂模式(Abstract Factory Pattern),在工厂方法的基础上再抽象一层,用来管理多个工厂类,该超级工厂又称为其他工厂的工厂。
这是最复杂的一种。工厂方法关注的是“单个产品”(比如弹窗),而抽象工厂关注的是“产品族(一套相关的产品)”。

实现

ts
// --- 抽象产品族 ---
interface IButton { render(): void; }
interface IDialog { render(): void; }

// --- 具体产品 (Mac系列) ---
class MacButton implements IButton { render() { console.log("渲染 Mac 风格按钮"); } }
class MacDialog implements IDialog { render() { console.log("渲染 Mac 风格弹窗"); } }

// --- 具体产品 (Win系列) ---
class WinButton implements IButton { render() { console.log("渲染 Win 风格按钮"); } }
class WinDialog implements IDialog { render() { console.log("渲染 Win 风格弹窗"); } }

// === 核心:抽象工厂 (定义一套系列产品的生产线) ===
interface IThemeFactory {
  createButton(): IButton;
  createDialog(): IDialog;
}

// === 具体工厂 (按系列生产) ===
class MacThemeFactory implements IThemeFactory {
  createButton() { return new MacButton(); }
  createDialog() { return new MacDialog(); }
}
class WinThemeFactory implements IThemeFactory {
  createButton() { return new WinButton(); }
  createDialog() { return new WinDialog(); }
}

// --- 业务调用 ---
// 根据用户系统,只实例化一个工厂,就能保证产出的组件风格绝对统一!
function renderUI(factory: IThemeFactory) {
  const btn = factory.createButton();
  const dialog = factory.createDialog();
  btn.render();
  dialog.render();
}

// 如果是 Mac 用户:
renderUI(new MacThemeFactory()); 
// 打印:渲染 Mac 风格按钮 \n 渲染 Mac 风格弹窗