什么是抽象工厂模式?

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供一个接口用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。

与工厂方法模式(单个产品对应单个工厂)不同,抽象工厂模式聚焦于产品族(一组相关联的产品,如 “中式家具” 包含椅子、桌子、沙发,“西式家具” 也包含对应产品)的创建,通过抽象工厂接口定义产品族的创建方法,由具体工厂实现不同产品族的创建逻辑。

抽象工厂模式的核心角色

  1. 抽象工厂(Abstract Factory):声明创建产品族中各类产品的抽象方法(如创建椅子、桌子)。
  2. 具体工厂(Concrete Factory):实现抽象工厂的方法,创建某一产品族的具体产品(如 “中式工厂” 创建中式椅子、中式桌子)。
  3. 抽象产品(Abstract Product):定义产品族中某类产品的公共接口(如 “椅子”“桌子” 各自的抽象接口)。
  4. 具体产品(Concrete Product):实现抽象产品接口,是具体工厂创建的目标(如 “中式椅子”“西式桌子”)。

JavaScript 实现抽象工厂模式示例:家具工厂

以下以 “家具生产” 为例,实现抽象工厂模式。场景是:存在 “现代风格” 和 “复古风格” 两个产品族,每个产品族包含椅子、桌子两种产品。客户端通过具体工厂(现代工厂 / 复古工厂)获取对应风格的一整套家具,无需关心具体产品的创建细节。

代码实现 - javascript
// -------------- 1. 抽象产品:家具的抽象接口 --------------
// 抽象椅子
class Chair {
  sitOn() {
    throw new Error("子类必须实现 sitOn 方法");
  }
}

// 抽象桌子
class Table {
  putThings() {
    throw new Error("子类必须实现 putThings 方法");
  }
}

// -------------- 2. 具体产品:现代风格家具 --------------
// 现代椅子
class ModernChair extends Chair {
  sitOn() {
    console.log("坐在现代风格椅子上(简约设计,舒适靠背)");
  }
}

// 现代桌子
class ModernTable extends Table {
  putThings() {
    console.log("在现代风格桌子上放东西(钢化玻璃桌面,金属支架)");
  }
}

// -------------- 3. 具体产品:复古风格家具 --------------
// 复古椅子
class VintageChair extends Chair {
  sitOn() {
    console.log("坐在复古风格椅子上(实木雕花,皮质坐垫)");
  }
}

// 复古桌子
class VintageTable extends Table {
  putThings() {
    console.log("在复古风格桌子上放东西(红木材质,圆形桌面)");
  }
}

// -------------- 4. 抽象工厂:家具工厂接口 --------------
class FurnitureFactory {
  // 创建椅子(抽象方法)
  createChair() {
    throw new Error("子类必须实现 createChair 方法");
  }

  // 创建桌子(抽象方法)
  createTable() {
    throw new Error("子类必须实现 createTable 方法");
  }
}

// -------------- 5. 具体工厂:现代风格工厂 --------------
class ModernFurnitureFactory extends FurnitureFactory {
  createChair() {
    return new ModernChair(); // 生产现代椅子
  }

  createTable() {
    return new ModernTable(); // 生产现代桌子
  }
}

// -------------- 6. 具体工厂:复古风格工厂 --------------
class VintageFurnitureFactory extends FurnitureFactory {
  createChair() {
    return new VintageChair(); // 生产复古椅子
  }

  createTable() {
    return new VintageTable(); // 生产复古桌子
  }
}

// -------------- 7. 客户端使用 --------------
// 客户端函数:根据工厂获取一整套家具并使用
function decorateRoom(factory) {
  const chair = factory.createChair();
  const table = factory.createTable();

  console.log("=== 布置房间 ===");
  chair.sitOn();
  table.putThings();
}

// 使用现代风格家具
const modernFactory = new ModernFurnitureFactory();
decorateRoom(modernFactory);
// 输出:
// === 布置房间 ===
// 坐在现代风格椅子上(简约设计,舒适靠背)
// 在现代风格桌子上放东西(钢化玻璃桌面,金属支架)

// 使用复古风格家具
const vintageFactory = new VintageFurnitureFactory();
decorateRoom(vintageFactory);
// 输出:
// === 布置房间 ===
// 坐在复古风格椅子上(实木雕花,皮质坐垫)
// 在复古风格桌子上放东西(红木材质,圆形桌面)

代码说明

  1. 抽象产品(Chair、Table):定义了 “椅子” 和 “桌子” 的通用接口(sitOnputThings),确保同一类产品具有一致的行为。
  2. 具体产品(ModernChair、VintageTable 等):实现了抽象产品接口,是不同风格的具体家具,属于产品族的组成部分。
  3. 抽象工厂(FurnitureFactory):声明了创建产品族的抽象方法(createChaircreateTable),规定具体工厂必须能生产一整套相关产品。
  4. 具体工厂(ModernFurnitureFactory 等):每个工厂对应一个产品族(现代 / 复古),实现抽象工厂的方法,返回该风格的具体产品。
  5. 客户端:通过具体工厂获取产品,无需知道产品的具体类型,只需调用产品的通用接口,实现了 “风格切换” 与 “产品使用” 的解耦。

抽象工厂模式的优势

  • 产品族一致性:确保同一产品族的产品(如现代椅子和现代桌子)能相互匹配,避免风格冲突。
  • 隔离具体类:客户端只依赖抽象工厂和抽象产品,无需关心具体产品的类名,降低耦合。
  • 便于切换产品族:更换具体工厂即可切换整套产品(如从现代风格换成复古风格),符合 “开闭原则”。

适用场景

  • 系统需要依赖多个产品族,且产品族可能频繁切换(如主题切换:浅色主题 / 深色主题的按钮、输入框等组件)。
  • 产品之间存在关联或约束(如数据库访问:MySQL 的 Connection 和 Statement 需配套使用,不能与 Oracle 的组件混合)。

与工厂方法模式的区别

维度 工厂方法模式 抽象工厂模式
关注对象 单个产品的创建 产品族(一组相关产品)的创建
工厂职责 每个工厂创建一种产品 每个工厂创建一族产品
扩展方式 新增产品需新增工厂 新增产品族需新增工厂,新增产品需修改所有工厂(缺点)

抽象工厂模式更适合处理 “产品族” 场景,但灵活性略低于工厂方法模式(新增单一产品时需修改所有工厂)。实际开发中需根据产品间的关联程度选择。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐