Skip to content

抽象工厂模式详解:概念、实现与应用

引言

抽象工厂模式是创建型设计模式中的一个重要模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式是工厂方法模式的进一步扩展,它关注的是产品族的创建,而不是单一产品的创建。

什么是抽象工厂模式?

抽象工厂模式是一种创建型设计模式,它能创建一系列相关的对象,而无需指定其具体类。抽象工厂模式关注的是产品族的概念,一个产品族是一组相关或相互依赖的产品。

核心思想

抽象工厂模式的核心思想是:

  1. 产品族概念:一组相关或相互依赖的产品
  2. 接口抽象:定义创建产品族的接口
  3. 具体实现:具体工厂实现接口,创建具体产品族

为什么需要抽象工厂模式?

在许多情况下,我们需要创建一组相关的产品对象:

1. 产品族一致性

当需要确保一组相关的产品对象一起使用时:

  • UI 组件的风格一致性(Windows 风格、Mac 风格)
  • 数据库访问的一致性(连接、命令、适配器等)
  • 游戏中的角色装备一致性

2. 系统平台兼容性

当系统需要支持多个平台时:

  • 不同操作系统的 UI 组件
  • 不同数据库的访问组件
  • 不同设备的驱动程序

3. 产品配置管理

当需要管理复杂的产品配置时:

  • 产品族的版本管理
  • 产品族的兼容性检查
  • 产品族的替换和升级

抽象工厂模式的基本实现

让我们从一个简单的抽象工厂模式实现开始:

javascript
// 抽象产品 A
class AbstractProductA {
  operationA() {
    throw new Error('必须实现 operationA 方法');
  }
}

// 抽象产品 B
class AbstractProductB {
  operationB() {
    throw new Error('必须实现 operationB 方法');
  }
  
  anotherOperationB(collaborator) {
    throw new Error('必须实现 anotherOperationB 方法');
  }
}

// 具体产品 A1
class ConcreteProductA1 extends AbstractProductA {
  operationA() {
    return 'ConcreteProductA1 的结果';
  }
}

// 具体产品 A2
class ConcreteProductA2 extends AbstractProductA {
  operationA() {
    return 'ConcreteProductA2 的结果';
  }
}

// 具体产品 B1
class ConcreteProductB1 extends AbstractProductB {
  operationB() {
    return 'ConcreteProductB1 的结果';
  }
  
  anotherOperationB(collaborator) {
    const result = collaborator.operationA();
    return `ConcreteProductB1 与 (${result}) 协作`;
  }
}

// 具体产品 B2
class ConcreteProductB2 extends AbstractProductB {
  operationB() {
    return 'ConcreteProductB2 的结果';
  }
  
  anotherOperationB(collaborator) {
    const result = collaborator.operationA();
    return `ConcreteProductB2 与 (${result}) 协作`;
  }
}

// 抽象工厂
class AbstractFactory {
  createProductA() {
    throw new Error('必须实现 createProductA 方法');
  }
  
  createProductB() {
    throw new Error('必须实现 createProductB 方法');
  }
}

// 具体工厂 1
class ConcreteFactory1 extends AbstractFactory {
  createProductA() {
    return new ConcreteProductA1();
  }
  
  createProductB() {
    return new ConcreteProductB1();
  }
}

// 具体工厂 2
class ConcreteFactory2 extends AbstractFactory {
  createProductA() {
    return new ConcreteProductA2();
  }
  
  createProductB() {
    return new ConcreteProductB2();
  }
}

// 客户端代码
function clientCode(factory) {
  const productA = factory.createProductA();
  const productB = factory.createProductB();
  
  console.log(productB.operationB());
  console.log(productB.anotherOperationB(productA));
}

// 使用具体工厂 1
console.log('客户端:使用 ConcreteFactory1 的产品族');
clientCode(new ConcreteFactory1());

console.log('');

// 使用具体工厂 2
console.log('客户端:使用 ConcreteFactory2 的产品族');
clientCode(new ConcreteFactory2());

实现要点分析

  1. 产品族结构:定义多个产品接口和具体产品实现
  2. 工厂接口:定义创建产品族的接口
  3. 具体工厂:实现工厂接口,创建具体产品族
  4. 产品协作:产品之间可以相互协作

抽象工厂模式的实际应用场景

1. 跨平台 UI 组件库

在开发跨平台应用程序时,抽象工厂模式非常适合用于创建不同平台的 UI 组件:

javascript
// UI 组件抽象接口
class Button {
  render() {
    throw new Error('必须实现 render 方法');
  }
}

class Checkbox {
  render() {
    throw new Error('必须实现 render 方法');
  }
  
  check() {
    throw new Error('必须实现 check 方法');
  }
}

// Windows 风格组件
class WindowsButton extends Button {
  render() {
    return '<button class="windows-button">Windows 按钮</button>';
  }
}

class WindowsCheckbox extends Checkbox {
  render() {
    return '<input type="checkbox" class="windows-checkbox" />';
  }
  
  check() {
    return 'Windows 复选框被选中';
  }
}

// Mac 风格组件
class MacButton extends Button {
  render() {
    return '<button class="mac-button">Mac 按钮</button>';
  }
}

class MacCheckbox extends Checkbox {
  render() {
    return '<input type="checkbox" class="mac-checkbox" />';
  }
  
  check() {
    return 'Mac 复选框被选中';
  }
}

// UI 工厂抽象接口
class GUIFactory {
  createButton() {
    throw new Error('必须实现 createButton 方法');
  }
  
  createCheckbox() {
    throw new Error('必须实现 createCheckbox 方法');
  }
}

// Windows 工厂
class WindowsFactory extends GUIFactory {
  createButton() {
    return new WindowsButton();
  }
  
  createCheckbox() {
    return new WindowsCheckbox();
  }
}

// Mac 工厂
class MacFactory extends GUIFactory {
  createButton() {
    return new MacButton();
  }
  
  createCheckbox() {
    return new MacCheckbox();
  }
}

// 应用程序类
class Application {
  constructor(factory) {
    this.factory = factory;
    this.button = null;
    this.checkbox = null;
  }
  
  createUI() {
    this.button = this.factory.createButton();
    this.checkbox = this.factory.createCheckbox();
  }
  
  render() {
    if (!this.button || !this.checkbox) {
      throw new Error('UI 未创建');
    }
    
    return {
      button: this.button.render(),
      checkbox: this.checkbox.render()
    };
  }
  
  handleCheckboxClick() {
    if (!this.checkbox) {
      throw new Error('复选框未创建');
    }
    return this.checkbox.check();
  }
}

// 使用示例
function createApplication(platform) {
  let factory;
  
  switch (platform) {
    case 'windows':
      factory = new WindowsFactory();
      break;
    case 'mac':
      factory = new MacFactory();
      break;
    default:
      throw new Error(`不支持的平台: ${platform}`);
  }
  
  const app = new Application(factory);
  app.createUI();
  return app;
}

// Windows 应用
const windowsApp = createApplication('windows');
console.log('Windows 应用 UI:', windowsApp.render());
console.log(windowsApp.handleCheckboxClick());

// Mac 应用
const macApp = createApplication('mac');
console.log('Mac 应用 UI:', macApp.render());
console.log(macApp.handleCheckboxClick());

2. 数据库访问组件族

在企业级应用中,抽象工厂模式可以用于创建不同数据库的访问组件:

javascript
// 数据库连接接口
class Connection {
  connect() {
    throw new Error('必须实现 connect 方法');
  }
  
  close() {
    throw new Error('必须实现 close 方法');
  }
}

// 命令接口
class Command {
  execute(sql) {
    throw new Error('必须实现 execute 方法');
  }
}

// 数据适配器接口
class DataAdapter {
  fetch(query) {
    throw new Error('必须实现 fetch 方法');
  }
  
  save(data) {
    throw new Error('必须实现 save 方法');
  }
}

// MySQL 组件
class MySQLConnection extends Connection {
  connect() {
    return '连接到 MySQL 数据库';
  }
  
  close() {
    return '关闭 MySQL 连接';
  }
}

class MySQLCommand extends Command {
  execute(sql) {
    return `在 MySQL 中执行 SQL: ${sql}`;
  }
}

class MySQLDataAdapter extends DataAdapter {
  fetch(query) {
    return `MySQL 获取数据: ${query}`;
  }
  
  save(data) {
    return `MySQL 保存数据: ${JSON.stringify(data)}`;
  }
}

// PostgreSQL 组件
class PostgreSQLConnection extends Connection {
  connect() {
    return '连接到 PostgreSQL 数据库';
  }
  
  close() {
    return '关闭 PostgreSQL 连接';
  }
}

class PostgreSQLCommand extends Command {
  execute(sql) {
    return `在 PostgreSQL 中执行 SQL: ${sql}`;
  }
}

class PostgreSQLDataAdapter extends DataAdapter {
  fetch(query) {
    return `PostgreSQL 获取数据: ${query}`;
  }
  
  save(data) {
    return `PostgreSQL 保存数据: ${JSON.stringify(data)}`;
  }
}

// 数据库工厂接口
class DatabaseFactory {
  createConnection() {
    throw new Error('必须实现 createConnection 方法');
  }
  
  createCommand() {
    throw new Error('必须实现 createCommand 方法');
  }
  
  createDataAdapter() {
    throw new Error('必须实现 createDataAdapter 方法');
  }
}

// MySQL 工厂
class MySQLFactory extends DatabaseFactory {
  createConnection() {
    return new MySQLConnection();
  }
  
  createCommand() {
    return new MySQLCommand();
  }
  
  createDataAdapter() {
    return new MySQLDataAdapter();
  }
}

// PostgreSQL 工厂
class PostgreSQLFactory extends DatabaseFactory {
  createConnection() {
    return new PostgreSQLConnection();
  }
  
  createCommand() {
    return new PostgreSQLCommand();
  }
  
  createDataAdapter() {
    return new PostgreSQLDataAdapter();
  }
}

// 数据访问上下文
class DatabaseContext {
  constructor(factory) {
    this.factory = factory;
    this.connection = null;
    this.command = null;
    this.dataAdapter = null;
  }
  
  initialize() {
    this.connection = this.factory.createConnection();
    this.command = this.factory.createCommand();
    this.dataAdapter = this.factory.createDataAdapter();
  }
  
  connect() {
    if (!this.connection) {
      throw new Error('数据库上下文未初始化');
    }
    return this.connection.connect();
  }
  
  executeSQL(sql) {
    if (!this.command) {
      throw new Error('数据库上下文未初始化');
    }
    return this.command.execute(sql);
  }
  
  fetchData(query) {
    if (!this.dataAdapter) {
      throw new Error('数据库上下文未初始化');
    }
    return this.dataAdapter.fetch(query);
  }
  
  saveData(data) {
    if (!this.dataAdapter) {
      throw new Error('数据库上下文未初始化');
    }
    return this.dataAdapter.save(data);
  }
  
  disconnect() {
    if (this.connection) {
      return this.connection.close();
    }
  }
}

// 使用示例
function createDatabaseContext(dbType) {
  let factory;
  
  switch (dbType) {
    case 'mysql':
      factory = new MySQLFactory();
      break;
    case 'postgresql':
      factory = new PostgreSQLFactory();
      break;
    default:
      throw new Error(`不支持的数据库类型: ${dbType}`);
  }
  
  const context = new DatabaseContext(factory);
  context.initialize();
  return context;
}

// MySQL 使用示例
const mysqlContext = createDatabaseContext('mysql');
console.log(mysqlContext.connect());
console.log(mysqlContext.executeSQL('SELECT * FROM users'));
console.log(mysqlContext.fetchData('SELECT * FROM users WHERE id = 1'));
console.log(mysqlContext.saveData({ name: '张三', age: 30 }));
console.log(mysqlContext.disconnect());

// PostgreSQL 使用示例
const postgresqlContext = createDatabaseContext('postgresql');
console.log(postgresqlContext.connect());
console.log(postgresqlContext.executeSQL('SELECT * FROM users'));
console.log(postgresqlContext.fetchData('SELECT * FROM users WHERE id = 1'));
console.log(postgresqlContext.saveData({ name: '李四', age: 25 }));
console.log(postgresqlContext.disconnect());

3. 游戏角色装备系统

在游戏开发中,抽象工厂模式可以用于创建不同主题的角色装备:

javascript
// 装备接口
class Weapon {
  getType() {
    throw new Error('必须实现 getType 方法');
  }
  
  attack() {
    throw new Error('必须实现 attack 方法');
  }
}

class Armor {
  getType() {
    throw new Error('必须实现 getType 方法');
  }
  
  defend() {
    throw new Error('必须实现 defend 方法');
  }
}

class Mount {
  getType() {
    throw new Error('必须实现 getType 方法');
  }
  
  move() {
    throw new Error('必须实现 move 方法');
  }
}

// 中世纪主题装备
class MedievalSword extends Weapon {
  getType() {
    return '中世纪剑';
  }
  
  attack() {
    return '挥舞中世纪剑进行攻击';
  }
}

class MedievalArmor extends Armor {
  getType() {
    return '中世纪盔甲';
  }
  
  defend() {
    return '穿上中世纪盔甲进行防御';
  }
}

class MedievalHorse extends Mount {
  getType() {
    return '中世纪战马';
  }
  
  move() {
    return '骑着中世纪战马冲锋';
  }
}

// 未来主题装备
class LaserGun extends Weapon {
  getType() {
    return '激光枪';
  }
  
  attack() {
    return '使用激光枪进行攻击';
  }
}

class EnergyShield extends Armor {
  getType() {
    return '能量护盾';
  }
  
  defend() {
    return '激活能量护盾进行防御';
  }
}

class Hovercraft extends Mount {
  getType() {
    return '悬浮车';
  }
  
  move() {
    return '驾驶悬浮车快速移动';
  }
}

// 装备工厂接口
class EquipmentFactory {
  createWeapon() {
    throw new Error('必须实现 createWeapon 方法');
  }
  
  createArmor() {
    throw new Error('必须实现 createArmor 方法');
  }
  
  createMount() {
    throw new Error('必须实现 createMount 方法');
  }
}

// 中世纪装备工厂
class MedievalEquipmentFactory extends EquipmentFactory {
  createWeapon() {
    return new MedievalSword();
  }
  
  createArmor() {
    return new MedievalArmor();
  }
  
  createMount() {
    return new MedievalHorse();
  }
}

// 未来装备工厂
class FutureEquipmentFactory extends EquipmentFactory {
  createWeapon() {
    return new LaserGun();
  }
  
  createArmor() {
    return new EnergyShield();
  }
  
  createMount() {
    return new Hovercraft();
  }
}

// 角色类
class Character {
  constructor(factory, name) {
    this.factory = factory;
    this.name = name;
    this.weapon = null;
    this.armor = null;
    this.mount = null;
  }
  
  equip() {
    this.weapon = this.factory.createWeapon();
    this.armor = this.factory.createArmor();
    this.mount = this.factory.createMount();
  }
  
  getEquipmentInfo() {
    if (!this.weapon || !this.armor || !this.mount) {
      throw new Error('角色未装备');
    }
    
    return {
      name: this.name,
      weapon: this.weapon.getType(),
      armor: this.armor.getType(),
      mount: this.mount.getType()
    };
  }
  
  attack() {
    if (!this.weapon) {
      throw new Error('角色未装备武器');
    }
    return `${this.name} ${this.weapon.attack()}`;
  }
  
  defend() {
    if (!this.armor) {
      throw new Error('角色未装备盔甲');
    }
    return `${this.name} ${this.armor.defend()}`;
  }
  
  move() {
    if (!this.mount) {
      throw new Error('角色未装备坐骑');
    }
    return `${this.name} ${this.mount.move()}`;
  }
}

// 使用示例
function createCharacter(theme, name) {
  let factory;
  
  switch (theme) {
    case 'medieval':
      factory = new MedievalEquipmentFactory();
      break;
    case 'future':
      factory = new FutureEquipmentFactory();
      break;
    default:
      throw new Error(`不支持的主题: ${theme}`);
  }
  
  const character = new Character(factory, name);
  character.equip();
  return character;
}

// 中世纪角色
const knight = createCharacter('medieval', '骑士');
console.log('骑士装备:', knight.getEquipmentInfo());
console.log(knight.attack());
console.log(knight.defend());
console.log(knight.move());

// 未来角色
const soldier = createCharacter('future', '士兵');
console.log('士兵装备:', soldier.getEquipmentInfo());
console.log(soldier.attack());
console.log(soldier.defend());
console.log(soldier.move());

抽象工厂模式与工厂方法模式的对比

工厂方法模式

javascript
// 工厂方法模式关注单一产品
class Creator {
  factoryMethod() {
    // 创建单一产品
  }
}

抽象工厂模式

javascript
// 抽象工厂模式关注产品族
class AbstractFactory {
  createProductA() {
    // 创建产品 A
  }
  
  createProductB() {
    // 创建产品 B
  }
  
  createProductC() {
    // 创建产品 C
  }
}

对比总结

特性工厂方法模式抽象工厂模式
关注点单一产品产品族
扩展性添加新产品需要新工厂添加新产品族需要新工厂
复杂度较低较高
适用场景单一产品创建一组相关产品创建

抽象工厂模式的优缺点

优点

  1. 产品族一致性:确保创建的产品族具有一致性
  2. 符合开闭原则:添加新的产品族时无需修改现有代码
  3. 良好的封装性:客户端不需要知道具体产品的创建细节
  4. 易于替换产品族:可以轻松切换整个产品族

缺点

  1. 类数量增加:每增加一个产品族,就需要增加多个类
  2. 系统复杂度增加:引入了更多的抽象和继承关系
  3. 难以支持新产品等级:添加新产品等级需要修改工厂接口

总结

抽象工厂模式是创建型设计模式中的重要模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式关注的是产品族的概念,确保创建的产品具有一致性。

通过本章的学习,我们了解了:

  1. 抽象工厂模式的基本概念和核心思想
  2. 抽象工厂模式的实现方式
  3. 抽象工厂模式在实际开发中的应用场景(跨平台UI组件、数据库访问组件族、游戏角色装备系统)
  4. 抽象工厂模式与工厂方法模式的对比
  5. 抽象工厂模式的优缺点

抽象工厂模式在现代软件开发中应用广泛,特别是在需要创建一组相关产品对象的场景中,它可以很好地支持系统的扩展性和维护性。

在下一章中,我们将继续探讨其他创建型模式,如建造者模式。