工厂模式在 JavaScript 中的深度应用

在软件工程中,设计模式是解决常见问题的高效模板,而工厂模式(Factory Pattern)作为创建型模式之一,因其在对象创建方面的灵活性和可扩展性,广泛应用于各种编程语言,包括 JavaScript。JavaScript 作为一门动态、灵活的语言,其函数式和面向对象特性为工厂模式的实现提供了独特的舞台。


1. 工厂模式的基础

1.1 什么是工厂模式?

工厂模式是一种创建型设计模式,旨在通过一个工厂对象或函数来创建其他对象,而无需直接使用 new 关键字或显式调用构造函数。它的核心思想是将对象的创建逻辑封装起来,解耦客户端代码与具体类的实现。

工厂模式的主要目标:

  • 抽象创建过程:隐藏对象创建的复杂逻辑。
  • 提高可扩展性:支持动态添加新类型的对象。
  • 降低耦合:客户端只需与工厂交互,无需了解具体类。

在 JavaScript 中,工厂模式可以通过函数、类或对象字面量实现,灵活性极高。

1.2 工厂模式的类型

工厂模式通常分为以下几种:

  • 简单工厂(Simple Factory):通过一个工厂函数根据参数创建不同类型的对象。
  • 工厂方法(Factory Method):定义一个创建对象的接口,由子类实现具体创建逻辑。
  • 抽象工厂(Abstract Factory):创建一系列相关或依赖对象的工厂,适合复杂对象族。

本文将逐一探讨这些类型在 JavaScript 中的实现。

1.3 为什么在 JavaScript 中使用工厂模式?

JavaScript 的动态类型和原型继承特性使得工厂模式特别适合:

  • 动态类型:无需显式声明对象类型,工厂可以根据条件创建不同对象。
  • 函数式编程:工厂函数天然契合 JavaScript 的函数式风格。
  • 模块化开发:工厂模式便于在模块化代码中封装创建逻辑。
  • 前端场景:如组件渲染、数据模型实例化等场景需要动态创建对象。

2. 简单工厂模式

简单工厂模式是最基础的工厂模式,通过一个工厂函数根据输入参数返回不同类型的对象。

2.1 基本实现

假设我们要创建一个用户管理系统,支持不同类型的用户(如管理员、普通用户)。

javascript 复制代码
function UserFactory() {
  function Admin(name) {
    this.name = name;
    this.role = 'admin';
    this.permissions = ['read', 'write', 'delete'];
  }

  function Member(name) {
    this.name = name;
    this.role = 'member';
    this.permissions = ['read'];
  }

  return {
    createUser(type, name) {
      switch (type) {
        case 'admin':
          return new Admin(name);
        case 'member':
          return new Member(name);
        default:
          throw new Error('Invalid user type');
      }
    },
  };
}

const userFactory = UserFactory();
const admin = userFactory.createUser('admin', 'Alice');
const member = userFactory.createUser('member', 'Bob');

console.log(admin); // { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] }
console.log(member); // { name: 'Bob', role: 'member', permissions: ['read'] }

2.2 使用 ES6 类

使用类改写上述例子,增强可读性和类型安全:

javascript 复制代码
class User {
  constructor(name, role, permissions) {
    this.name = name;
    this.role = role;
    this.permissions = permissions;
  }
}

class Admin extends User {
  constructor(name) {
    super(name, 'admin', ['read', 'write', 'delete']);
  }
}

class Member extends User {
  constructor(name) {
    super(name, 'member', ['read']);
  }
}

class UserFactory {
  static createUser(type, name) {
    switch (type) {
      case 'admin':
        return new Admin(name);
      case 'member':
        return new Member(name);
      default:
        throw new Error('Invalid user type');
    }
  }
}

const admin = UserFactory.createUser('admin', 'Alice');
const member = UserFactory.createUser('member', 'Bob');

console.log(admin); // Admin { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] }
console.log(member); // Member { name: 'Bob', role: 'member', permissions: ['read'] }

2.3 动态注册类型

为提高扩展性,可以允许动态注册新用户类型:

javascript 复制代码
class UserFactory {
  constructor() {
    this.types = new Map();
  }

  registerType(type, constructor) {
    this.types.set(type, constructor);
  }

  createUser(type, name) {
    const Constructor = this.types.get(type);
    if (!Constructor) {
      throw new Error(`Invalid user type: ${type}`);
    }
    return new Constructor(name);
  }
}

class Admin {
  constructor(name) {
    this.name = name;
    this.role = 'admin';
    this.permissions = ['read', 'write', 'delete'];
  }
}

class Member {
  constructor(name) {
    this.name = name;
    this.role = 'member';
    this.permissions = ['read'];
  }
}

const userFactory = new UserFactory();
userFactory.registerType('admin', Admin);
userFactory.registerType('member', Member);

const admin = userFactory.createUser('admin', 'Alice');
const member = userFactory.createUser('member', 'Bob');

console.log(admin); // Admin { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] }
console.log(member); // Member { name: 'Bob', role: 'member', permissions: ['read'] }

2.4 应用场景

简单工厂模式适用于:

  • 对象类型有限:如用户角色、UI 组件类型。
  • 创建逻辑简单:无需复杂的初始化过程。
  • 集中管理:希望将对象创建逻辑统一封装。

3. 工厂方法模式

工厂方法模式通过定义一个抽象工厂接口,由子类实现具体创建逻辑,适合需要更高灵活性和扩展性的场景。

3.1 基本实现

假设我们要为不同类型的文档(PDF、Word)创建编辑器。

javascript 复制代码
class DocumentEditor {
  createDocument() {
    throw new Error('Method must be implemented');
  }
}

class PdfEditor extends DocumentEditor {
  createDocument() {
    return {
      type: 'PDF',
      open: () => console.log('Opening PDF document'),
      save: () => console.log('Saving PDF document'),
    };
  }
}

class WordEditor extends DocumentEditor {
  createDocument() {
    return {
      type: 'Word',
      open: () => console.log('Opening Word document'),
      save: () => console.log('Saving Word document'),
    };
  }
}

function createEditor(type) {
  switch (type) {
    case 'pdf':
      return new PdfEditor();
    case 'word':
      return new WordEditor();
    default:
      throw new Error('Invalid editor type');
  }
}

const pdfEditor = createEditor('pdf');
const wordEditor = createEditor('word');

const pdfDoc = pdfEditor.createDocument();
const wordDoc = wordEditor.createDocument();

pdfDoc.open(); // Opening PDF document
wordDoc.save(); // Saving Word document

3.2 使用工厂类

将工厂逻辑封装为类:

javascript 复制代码
class Document {
  open() {
    throw new Error('Method must be implemented');
  }
  save() {
    throw new Error('Method must be implemented');
  }
}

class PdfDocument extends Document {
  open() {
    console.log('Opening PDF document');
  }
  save() {
    console.log('Saving PDF document');
  }
}

class WordDocument extends Document {
  open() {
    console.log('Opening Word document');
  }
  save() {
    console.log('Saving Word document');
  }
}

class DocumentFactory {
  createDocument() {
    throw new Error('Method must be implemented');
  }
}

class PdfFactory extends DocumentFactory {
  createDocument() {
    return new PdfDocument();
  }
}

class WordFactory extends DocumentFactory {
  createDocument() {
    return new WordDocument();
  }
}

const pdfFactory = new PdfFactory();
const wordFactory = new WordFactory();

const pdfDoc = pdfFactory.createDocument();
const wordDoc = wordFactory.createDocument();

pdfDoc.open(); // Opening PDF document
wordDoc.save(); // Saving Word document

3.3 动态工厂

支持动态添加工厂类型:

javascript 复制代码
class DocumentFactory {
  constructor() {
    this.factories = new Map();
  }

  registerFactory(type, factory) {
    this.factories.set(type, factory);
  }

  createDocument(type) {
    const factory = this.factories.get(type);
    if (!factory) {
      throw new Error(`Invalid document type: ${type}`);
    }
    return factory.createDocument();
  }
}

const documentFactory = new DocumentFactory();
documentFactory.registerFactory('pdf', new PdfFactory());
documentFactory.registerFactory('word', new WordFactory());

const pdfDoc = documentFactory.createDocument('pdf');
const wordDoc = documentFactory.createDocument('word');

pdfDoc.open(); // Opening PDF document
wordDoc.save(); // Saving Word document

3.4 应用场景

工厂方法模式适用于:

  • 需要子类扩展:如不同类型的编辑器、渲染器。
  • 创建逻辑复杂:涉及多步骤初始化。
  • 动态类型选择:运行时决定创建哪种对象。

4. 抽象工厂模式

抽象工厂模式用于创建一系列相关或依赖对象的工厂,适合复杂对象族的场景。

4.1 基本实现

假设我们要为不同平台(Web、Mobile)创建 UI 组件(如按钮、下拉框)。

javascript 复制代码
class Button {
  render() {
    throw new Error('Method must be implemented');
  }
}

class Dropdown {
  render() {
    throw new Error('Method must be implemented');
  }
}

class WebButton extends Button {
  render() {
    console.log('Rendering Web button');
  }
}

class WebDropdown extends Dropdown {
  render() {
    console.log('Rendering Web dropdown');
  }
}

class MobileButton extends Button {
  render() {
    console.log('Rendering Mobile button');
  }
}

class MobileDropdown extends Dropdown {
  render() {
    console.log('Rendering Mobile dropdown');
  }
}

class UIFactory {
  createButton() {
    throw new Error('Method must be implemented');
  }
  createDropdown() {
    throw new Error('Method must be implemented');
  }
}

class WebUIFactory extends UIFactory {
  createButton() {
    return new WebButton();
  }
  createDropdown() {
    return new WebDropdown();
  }
}

class MobileUIFactory extends UIFactory {
  createButton() {
    return new MobileButton();
  }
  createDropdown() {
    return new MobileDropdown();
  }
}

function createUIFactory(platform) {
  switch (platform) {
    case 'web':
      return new WebUIFactory();
    case 'mobile':
      return new MobileUIFactory();
    default:
      throw new Error('Invalid platform');
  }
}

const webFactory = createUIFactory('web');
const mobileFactory = createUIFactory('mobile');

const webButton = webFactory.createButton();
const webDropdown = webFactory.createDropdown();
const mobileButton = mobileFactory.createButton();
const mobileDropdown = mobileFactory.createDropdown();

webButton.render(); // Rendering Web button
mobileDropdown.render(); // Rendering Mobile dropdown

4.2 使用对象字面量

在 JavaScript 中,可以用对象字面量简化抽象工厂:

javascript 复制代码
const WebUIFactory = {
  createButton() {
    return {
      render: () => console.log('Rendering Web button'),
    };
  },
  createDropdown() {
    return {
      render: () => console.log('Rendering Web dropdown'),
    };
  },
};

const MobileUIFactory = {
  createButton() {
    return {
      render: () => console.log('Rendering Mobile button'),
    };
  },
  createDropdown() {
    return {
      render: () => console.log('Rendering Mobile dropdown'),
    };
  },
};

const factories = {
  web: WebUIFactory,
  mobile: MobileUIFactory,
};

function createUIFactory(platform) {
  const factory = factories[platform];
  if (!factory) {
    throw new Error(`Invalid platform: ${platform}`);
  }
  return factory;
}

const webFactory = createUIFactory('web');
const mobileFactory = createUIFactory('mobile');

webFactory.createButton().render(); // Rendering Web button
mobileFactory.createDropdown().render(); // Rendering Mobile dropdown

4.3 应用场景

抽象工厂模式适用于:

  • 相关对象族:如 UI 组件、数据库连接驱动。
  • 跨平台开发:Web、移动或桌面应用的组件创建。
  • 复杂初始化:需要创建一组相互依赖的对象。

5. 工厂模式与 TypeScript

TypeScript 的静态类型系统为工厂模式提供了更强的类型安全。

5.1 简单工厂

typescript 复制代码
interface User {
  name: string;
  role: string;
  permissions: string[];
}

class Admin implements User {
  name: string;
  role = 'admin';
  permissions = ['read', 'write', 'delete'];

  constructor(name: string) {
    this.name = name;
  }
}

class Member implements User {
  name: string;
  role = 'member';
  permissions = ['read'];

  constructor(name: string) {
    this.name = name;
  }
}

class UserFactory {
  static createUser(type: 'admin' | 'member', name: string): User {
    switch (type) {
      case 'admin':
        return new Admin(name);
      case 'member':
        return new Member(name);
      default:
        throw new Error('Invalid user type');
    }
  }
}

const admin = UserFactory.createUser('admin', 'Alice');
const member = UserFactory.createUser('member', 'Bob');

console.log(admin); // Admin { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] }
console.log(member); // Member { name: 'Bob', role: 'member', permissions: ['read'] }

5.2 工厂方法

typescript 复制代码
interface Document {
  open(): void;
  save(): void;
}

class PdfDocument implements Document {
  open() {
    console.log('Opening PDF document');
  }
  save() {
    console.log('Saving PDF document');
  }
}

class WordDocument implements Document {
  open() {
    console.log('Opening Word document');
  }
  save() {
    console.log('Saving Word document');
  }
}

interface DocumentFactory {
  createDocument(): Document;
}

class PdfFactory implements DocumentFactory {
  createDocument(): Document {
    return new PdfDocument();
  }
}

class WordFactory implements DocumentFactory {
  createDocument(): Document {
    return new WordDocument();
  }
}

const pdfFactory: DocumentFactory = new PdfFactory();
const wordFactory: DocumentFactory = new WordFactory();

const pdfDoc = pdfFactory.createDocument();
const wordDoc = wordFactory.createDocument();

pdfDoc.open(); // Opening PDF document
wordDoc.save(); // Saving Word document

5.3 抽象工厂

typescript 复制代码
interface Button {
  render(): void;
}

interface Dropdown {
  render(): void;
}

interface UIFactory {
  createButton(): Button;
  createDropdown(): Dropdown;
}

class WebButton implements Button {
  render() {
    console.log('Rendering Web button');
  }
}

class WebDropdown implements Dropdown {
  render() {
    console.log('Rendering Web dropdown');
  }
}

class MobileButton implements Button {
  render() {
    console.log('Rendering Mobile button');
  }
}

class MobileDropdown implements Dropdown {
  render() {
    console.log('Rendering Mobile dropdown');
  }
}

class WebUIFactory implements UIFactory {
  createButton(): Button {
    return new WebButton();
  }
  createDropdown(): Dropdown {
    return new WebDropdown();
  }
}

class MobileUIFactory implements UIFactory {
  createButton(): Button {
    return new MobileButton();
  }
  createDropdown(): Dropdown {
    return new MobileDropdown();
  }
}

const webFactory: UIFactory = new WebUIFactory();
const mobileFactory: UIFactory = new MobileUIFactory();

webFactory.createButton().render(); // Rendering Web button
mobileFactory.createDropdown().render(); // Rendering Mobile dropdown

5.4 类型安全的动态工厂

typescript 复制代码
interface User {
  name: string;
  role: string;
  permissions: string[];
}

type UserConstructor = new (name: string) => User;

class UserFactory {
  private types: Map<string, UserConstructor> = new Map();

  registerType(type: string, constructor: UserConstructor) {
    this.types.set(type, constructor);
  }

  createUser(type: string, name: string): User {
    const Constructor = this.types.get(type);
    if (!Constructor) {
      throw new Error(`Invalid user type: ${type}`);
    }
    return new Constructor(name);
  }
}

const userFactory = new UserFactory();
userFactory.registerType('admin', Admin);
userFactory.registerType('member', Member);

const admin = userFactory.createUser('admin', 'Alice');
const member = userFactory.createUser('member', 'Bob');

6. 工厂模式在前端框架中的应用

6.1 React 组件工厂

在 React 中,工厂模式常用于动态创建组件。

javascript 复制代码
const Button = ({ label }) => <button>{label}</button>;
const Input = ({ placeholder }) => <input placeholder={placeholder} />;
const Card = ({ title }) => <div>{title}</div>;

const ComponentFactory = {
  button: Button,
  input: Input,
  card: Card,
};

function createComponent(type, props) {
  const Component = ComponentFactory[type];
  if (!Component) {
    throw new Error(`Invalid component type: ${type}`);
  }
  return <Component {...props} />;
}

// 使用
const App = () => (
  <div>
    {createComponent('button', { label: 'Click Me' })}
    {createComponent('input', { placeholder: 'Enter text' })}
    {createComponent('card', { title: 'Hello' })}
  </div>
);

6.2 Vue 组件工厂

在 Vue 中,动态组件可以通过工厂模式实现:

javascript 复制代码
import { defineComponent } from 'vue';

const Button = defineComponent({
  props: ['label'],
  template: `<button>{{ label }}</button>`,
});

const Input = defineComponent({
  props: ['placeholder'],
  template: `<input :placeholder="placeholder" />`,
});

const ComponentFactory = {
  button: Button,
  input: Input,
};

function createComponent(type, props) {
  const Component = ComponentFactory[type];
  if (!Component) {
    throw new Error(`Invalid component type: ${type}`);
  }
  return { component: Component, props };
}

// 使用
export default defineComponent({
  setup() {
    const components = [
      createComponent('button', { label: 'Click Me' }),
      createComponent('input', { placeholder: 'Enter text' }),
    ];

    return { components };
  },
  template: `
    <div>
      <component
        v-for="(item, index) in components"
        :key="index"
        :is="item.component"
        v-bind="item.props"
      />
    </div>
  `,
});

6.3 React + TypeScript

在 React 中结合 TypeScript:

typescript 复制代码
interface ComponentProps {
  [key: string]: any;
}

interface ComponentFactory {
  [key: string]: React.ComponentType<ComponentProps>;
}

const Button: React.FC<{ label: string }> = ({ label }) => <button>{label}</button>;
const Input: React.FC<{ placeholder: string }> = ({ placeholder }) => <input placeholder={placeholder} />;

const ComponentFactory: ComponentFactory = {
  button: Button,
  input: Input,
};

function createComponent(type: string, props: ComponentProps): JSX.Element {
  const Component = ComponentFactory[type];
  if (!Component) {
    throw new Error(`Invalid component type: ${type}`);
  }
  return <Component {...props} />;
}

const App: React.FC = () => (
  <div>
    {createComponent('button', { label: 'Click Me' })}
    {createComponent('input', { placeholder: 'Enter text' })}
  </div>
);

7. 工厂模式与函数式编程

JavaScript 的函数式编程特性为工厂模式提供了新的实现方式。

7.1 高阶函数工厂

使用高阶函数创建工厂:

javascript 复制代码
const createUserFactory = (role, permissions) => (name) => ({
  name,
  role,
  permissions,
});

const createAdmin = createUserFactory('admin', ['read', 'write', 'delete']);
const createMember = createUserFactory('member', ['read']);

const admin = createAdmin('Alice');
const member = createMember('Bob');

console.log(admin); // { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] }
console.log(member); // { name: 'Bob', role: 'member', permissions: ['read'] }

7.2 柯里化工厂

使用柯里化增强灵活性:

javascript 复制代码
const userFactory = (role) => (permissions) => (name) => ({
  name,
  role,
  permissions,
});

const adminFactory = userFactory('admin')(['read', 'write', 'delete']);
const memberFactory = userFactory('member')(['read']);

const admin = adminFactory('Alice');
const member = memberFactory('Bob');

console.log(admin); // { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] }
console.log(member); // { name: 'Bob', role: 'member', permissions: ['read'] }

7.3 结合 TypeScript

typescript 复制代码
interface User {
  name: string;
  role: string;
  permissions: string[];
}

type UserFactory = (name: string) => User;

const createUserFactory = (role: string, permissions: string[]): UserFactory => (
  name: string
): User => ({
  name,
  role,
  permissions,
});

const createAdmin = createUserFactory('admin', ['read', 'write', 'delete']);
const createMember = createUserFactory('member', ['read']);

const admin = createAdmin('Alice');
const member = createMember('Bob');

8. 性能优化

8.1 缓存工厂实例

为避免重复创建工厂,使用缓存:

javascript 复制代码
const factoryCache = new Map();

function getUserFactory(type) {
  if (factoryCache.has(type)) {
    return factoryCache.get(type);
  }

  const factory = {
    admin: () => (name) => ({
      name,
      role: 'admin',
      permissions: ['read', 'write', 'delete'],
    }),
    member: () => (name) => ({
      name,
      role: 'member',
      permissions: ['read'],
    }),
  }[type];

  if (!factory) {
    throw new Error(`Invalid type: ${type}`);
  }

  factoryCache.set(type, factory);
  return factory;
}

const adminFactory = getUserFactory('admin');
const memberFactory = getUserFactory('member');

const admin = adminFactory('Alice');
const member = memberFactory('Bob');

8.2 单例工厂

确保工厂返回单例实例:

javascript 复制代码
class UserFactory {
  private static instance: UserFactory;

  private constructor() {}

  static getInstance(): UserFactory {
    if (!UserFactory.instance) {
      UserFactory.instance = new UserFactory();
    }
    return UserFactory.instance;
  }

  createUser(type, name) {
    switch (type) {
      case 'admin':
        return { name, role: 'admin', permissions: ['read', 'write', 'delete'] };
      case 'member':
        return { name, role: 'member', permissions: ['read'] };
      default:
        throw new Error('Invalid user type');
    }
  }
}

const factory = UserFactory.getInstance();
const admin = factory.createUser('admin', 'Alice');
const member = factory.createUser('member', 'Bob');

8.3 避免过度创建

通过对象池复用对象:

javascript 复制代码
class UserPool {
  private pool: Map<string, any> = new Map();

  getUser(type, name) {
    const key = `${type}:${name}`;
    if (this.pool.has(key)) {
      return this.pool.get(key);
    }

    const user = {
      admin: { name, role: 'admin', permissions: ['read', 'write', 'delete'] },
      member: { name, role: 'member', permissions: ['read'] },
    }[type];

    if (!user) {
      throw new Error(`Invalid type: ${type}`);
    }

    this.pool.set(key, user);
    return user;
  }
}

const userPool = new UserPool();
const admin = userPool.getUser('admin', 'Alice');
const cachedAdmin = userPool.getUser('admin', 'Alice');

console.log(admin === cachedAdmin); // true

9. 工厂模式与现代 JavaScript 特性

9.1 异步工厂

处理异步创建逻辑:

javascript 复制代码
async function createUserFactory(type) {
  const response = await fetch(`/api/user-types/${type}`);
  const { role, permissions } = await response.json();

  return (name) => ({
    name,
    role,
    permissions,
  });
}

(async () => {
  const adminFactory = await createUserFactory('admin');
  const memberFactory = await createUserFactory('member');

  const admin = adminFactory('Alice');
  const member = memberFactory('Bob');

  console.log(admin);
  console.log(member);
})();

9.2 Proxy 增强工厂

使用 Proxy 动态拦截创建逻辑:

javascript 复制代码
const userFactory = new Proxy(
  {},
  {
    get(target, type) {
      const configs = {
        admin: { role: 'admin', permissions: ['read', 'write', 'delete'] },
        member: { role: 'member', permissions: ['read'] },
      };

      const config = configs[type];
      if (!config) {
        throw new Error(`Invalid type: ${type}`);
      }

      return (name) => ({
        name,
        ...config,
      });
    },
  }
);

const admin = userFactory.admin('Alice');
const member = userFactory.member('Bob');

console.log(admin); // { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] }
console.log(member); // { name: 'Bob', role: 'member', permissions: ['read'] }

9.3 Symbol 作为类型标识

使用 Symbol 提高类型安全性:

javascript 复制代码
const ADMIN = Symbol('admin');
const MEMBER = Symbol('member');

const UserFactory = {
  createUser(type, name) {
    const configs = {
      [ADMIN]: { role: 'admin', permissions: ['read', 'write', 'delete'] },
      [MEMBER]: { role: 'member', permissions: ['read'] },
    };

    const config = configs[type];
    if (!config) {
      throw new Error('Invalid user type');
    }

    return { name, ...config };
  },
};

const admin = UserFactory.createUser(ADMIN, 'Alice');
const member = UserFactory.createUser(MEMBER, 'Bob');

console.log(admin);
console.log(member);

10. 工厂模式在 Node.js 中的应用

10.1 数据库连接工厂

为不同数据库(MySQL、MongoDB)创建连接:

javascript 复制代码
class DatabaseConnection {
  connect() {
    throw new Error('Method must be implemented');
  }
}

class MySQLConnection extends DatabaseConnection {
  connect() {
    console.log('Connecting to MySQL');
  }
}

class MongoDBConnection extends DatabaseConnection {
  connect() {
    console.log('Connecting to MongoDB');
  }
}

class DatabaseFactory {
  static createConnection(type) {
    switch (type) {
      case 'mysql':
        return new MySQLConnection();
      case 'mongodb':
        return new MongoDBConnection();
      default:
        throw new Error('Invalid database type');
    }
  }
}

const mysqlConn = DatabaseFactory.createConnection('mysql');
const mongodbConn = DatabaseFactory.createConnection('mongodb');

mysqlConn.connect(); // Connecting to MySQL
mongodbConn.connect(); // Connecting to MongoDB

10.2 日志工厂

为不同日志级别创建日志器:

javascript 复制代码
class Logger {
  log(message) {
    throw new Error('Method must be implemented');
  }
}

class InfoLogger extends Logger {
  log(message) {
    console.log(`[INFO] ${message}`);
  }
}

class ErrorLogger extends Logger {
  log(message) {
    console.error(`[ERROR] ${message}`);
  }
}

const LoggerFactory = {
  createLogger(level) {
    const loggers = {
      info: InfoLogger,
      error: ErrorLogger,
    };

    const LoggerClass = loggers[level];
    if (!LoggerClass) {
      throw new Error(`Invalid log level: ${level}`);
    }

    return new LoggerClass();
  },
};

const infoLogger = LoggerFactory.createLogger('info');
const errorLogger = LoggerFactory.createLogger('error');

infoLogger.log('Operation completed'); // [INFO] Operation completed
errorLogger.log('Something went wrong'); // [ERROR] Something went wrong

11. 测试工厂模式

11.1 使用 Jest 测试简单工厂

javascript 复制代码
const UserFactory = require('./userFactory');

describe('UserFactory', () => {
  it('should create an admin user', () => {
    const admin = UserFactory.createUser('admin', 'Alice');
    expect(admin.role).toBe('admin');
    expect(admin.permissions).toEqual(['read', 'write', 'delete']);
  });

  it('should create a member user', () => {
    const member = UserFactory.createUser('member', 'Bob');
    expect(member.role).toBe('member');
    expect(member.permissions).toEqual(['read']);
  });

  it('should throw error for invalid type', () => {
    expect(() => UserFactory.createUser('invalid', 'Charlie')).toThrow('Invalid user type');
  });
});

11.2 测试 TypeScript 工厂

typescript 复制代码
import UserFactory from './userFactory';

describe('UserFactory', () => {
  it('should create an admin user', () => {
    const admin = UserFactory.createUser('admin', 'Alice');
    expect(admin.role).toBe('admin');
    expect(admin.permissions).toEqual(['read', 'write', 'delete']);
  });

  it('should create a member user', () => {
    const member = UserFactory.createUser('member', 'Bob');
    expect(member.role).toBe('member');
    expect(member.permissions).toEqual(['read']);
  });

  it('should throw error for invalid type', () => {
    expect(() => UserFactory.createUser('invalid' as any, 'Charlie')).toThrow('Invalid user type');
  });
});

12. 工厂模式与模块化

12.1 CommonJS 模块

javascript 复制代码
// userFactory.js
class Admin {
  constructor(name) {
    this.name = name;
    this.role = 'admin';
    this.permissions = ['read', 'write', 'delete'];
  }
}

class Member {
  constructor(name) {
    this.name = name;
    this.role = 'member';
    this.permissions = ['read'];
  }
}

module.exports = {
  createUser(type, name) {
    switch (type) {
      case 'admin':
        return new Admin(name);
      case 'member':
        return new Member(name);
      default:
        throw new Error('Invalid user type');
    }
  },
};

// app.js
const UserFactory = require('./userFactory');
const admin = UserFactory.createUser('admin', 'Alice');
console.log(admin);

12.2 ES Modules

javascript 复制代码
// userFactory.mjs
export class Admin {
  constructor(name) {
    this.name = name;
    this.role = 'admin';
    this.permissions = ['read', 'write', 'delete'];
  }
}

export class Member {
  constructor(name) {
    this.name = name;
    this.role = 'member';
    this.permissions = ['read'];
  }
}

export function createUser(type, name) {
  switch (type) {
    case 'admin':
      return new Admin(name);
    case 'member':
      return new Member(name);
    default:
      throw new Error('Invalid user type');
  }
}

// app.mjs
import { createUser } from './userFactory.mjs';
const admin = createUser('admin', 'Alice');
console.log(admin);

13. 工厂模式与依赖注入

工厂模式常与依赖注入结合,提升代码灵活性。

javascript 复制代码
class DatabaseService {
  query() {
    console.log('Executing database query');
  }
}

class AuthService {
  login() {
    console.log('User logged in');
  }
}

class ServiceFactory {
  static createService(type, dependencies = {}) {
    switch (type) {
      case 'database':
        return new DatabaseService(dependencies);
      case 'auth':
        return new AuthService(dependencies);
      default:
        throw new Error('Invalid service type');
    }
  }
}

const dbService = ServiceFactory.createService('database');
const authService = ServiceFactory.createService('auth', { db: dbService });

dbService.query(); // Executing database query
authService.login(); // User logged in

14. 工厂模式与异步场景

14.1 异步创建

javascript 复制代码
async function createApiClient(type) {
  const response = await fetch(`/api/config/${type}`);
  const config = await response.json();

  return {
    request: () => console.log(`Request with config: ${JSON.stringify(config)}`),
  };
}

(async () => {
  const userApi = await createApiClient('user');
  const orderApi = await createApiClient('order');

  userApi.request(); // Request with config: {...}
  orderApi.request(); // Request with config: {...}
})();

14.2 异步工厂类

javascript 复制代码
class ApiClientFactory {
  async createClient(type) {
    const response = await fetch(`/api/config/${type}`);
    const config = await response.json();

    return {
      request: () => console.log(`Request with config: ${JSON.stringify(config)}`),
    };
  }
}

const factory = new ApiClientFactory();

(async () => {
  const userApi = await factory.createClient('user');
  const orderApi = await factory.createClient('order');

  userApi.request();
  orderApi.request();
})();

15. 工厂模式与错误处理

15.1 集中错误处理

javascript 复制代码
class UserFactory {
  static createUser(type, name) {
    try {
      switch (type) {
        case 'admin':
          return { name, role: 'admin', permissions: ['read', 'write', 'delete'] };
        case 'member':
          return { name, role: 'member', permissions: ['read'] };
        default:
          throw new Error(`Invalid user type: ${type}`);
      }
    } catch (error) {
      console.error(`Factory error: ${error.message}`);
      throw error;
    }
  }
}

try {
  const admin = UserFactory.createUser('admin', 'Alice');
  const invalid = UserFactory.createUser('invalid', 'Charlie');
} catch (error) {
  console.log(`Caught error: ${error.message}`);
}

15.2 自定义错误

javascript 复制代码
class FactoryError extends Error {
  constructor(message) {
    super(message);
    this.name = 'FactoryError';
  }
}

class UserFactory {
  static createUser(type, name) {
    switch (type) {
      case 'admin':
        return { name, role: 'admin', permissions: ['read', 'write', 'delete'] };
      case 'member':
        return { name, role: 'member', permissions: ['read'] };
      default:
        throw new FactoryError(`Invalid user type: ${type}`);
    }
  }
}

try {
  const admin = UserFactory.createUser('admin', 'Alice');
  const invalid = UserFactory.createUser('invalid', 'Charlie');
} catch (error) {
  if (error instanceof FactoryError) {
    console.log(`Factory error: ${error.message}`);
  }
}

16. 工厂模式与单元测试

16.1 Mock 工厂

javascript 复制代码
const UserFactory = {
  createUser(type, name) {
    switch (type) {
      case 'admin':
        return { name, role: 'admin', permissions: ['read', 'write', 'delete'] };
      case 'member':
        return { name, role: 'member', permissions: ['read'] };
      default:
        throw new Error('Invalid user type');
    }
  },
};

jest.mock('./userFactory', () => ({
  createUser: jest.fn(),
}));

describe('UserFactory Mock', () => {
  it('should mock admin creation', () => {
    const mockUser = { name: 'Alice', role: 'admin', permissions: ['read', 'write', 'delete'] };
    require('./userFactory').createUser.mockReturnValue(mockUser);

    const admin = UserFactory.createUser('admin', 'Alice');
    expect(admin).toEqual(mockUser);
    expect(UserFactory.createUser).toHaveBeenCalledWith('admin', 'Alice');
  });
});

16.2 测试异步工厂

javascript 复制代码
const ApiClientFactory = {
  async createClient(type) {
    const response = await fetch(`/api/config/${type}`);
    const config = await response.json();
    return { request: () => config };
  },
};

jest.mock('./apiClientFactory', () => ({
  createClient: jest.fn(),
}));

describe('ApiClientFactory', () => {
  it('should mock async client creation', async () => {
    const mockClient = { request: () => ({ type: 'user' }) };
    require('./apiClientFactory').createClient.mockResolvedValue(mockClient);

    const client = await ApiClientFactory.createClient('user');
    expect(client).toEqual(mockClient);
    expect(ApiClientFactory.createClient).toHaveBeenCalledWith('user');
  });
});

17. 工厂模式与性能分析

17.1 内存管理

避免创建过多对象:

javascript 复制代码
class UserFactory {
  static cache = new Map();

  static createUser(type, name) {
    const key = `${type}:${name}`;
    if (this.cache.has(key)) {
      return this.cache.get(key);
    }

    const user = {
      admin: { name, role: 'admin', permissions: ['read', 'write', 'delete'] },
      member: { name, role: 'member', permissions: ['read'] },
    }[type];

    if (!user) {
      throw new Error(`Invalid type: ${type}`);
    }

    this.cache.set(key, user);
    return user;
  }
}

const admin1 = UserFactory.createUser('admin', 'Alice');
const admin2 = UserFactory.createUser('admin', 'Alice');

console.log(admin1 === admin2); // true

17.2 性能测试

使用 performance.now 测量工厂性能:

javascript 复制代码
const start = performance.now();

for (let i = 0; i < 1000; i++) {
  UserFactory.createUser('admin', `User${i}`);
}

const end = performance.now();
console.log(`Factory creation took ${end - start}ms`);

18. 工厂模式与前端状态管理

18.1 Redux Action 工厂

javascript 复制代码
const createAction = (type) => (payload) => ({
  type,
  payload,
});

const addUser = createAction('ADD_USER');
const removeUser = createAction('REMOVE_USER');

console.log(addUser({ name: 'Alice' })); // { type: 'ADD_USER', payload: { name: 'Alice' } }
console.log(removeUser({ id: 1 })); // { type: 'REMOVE_USER', payload: { id: 1 } }

18.2 Zustand 状态工厂

javascript 复制代码
import create from 'zustand';

const createUserStore = (role) => create((set) => ({
  users: [],
  addUser: (name) =>
    set((state) => ({
      users: [...state.users, { name, role }],
    })),
}));

const adminStore = createUserStore('admin');
const memberStore = createUserStore('member');

adminStore.getState().addUser('Alice');
memberStore.getState().addUser('Bob');

console.log(adminStore.getState().users); // [{ name: 'Alice', role: 'admin' }]
console.log(memberStore.getState().users); // [{ name: 'Bob', role: 'member' }]

19. 工厂模式与构建工具

19.1 Webpack Plugin 工厂

javascript 复制代码
class PluginFactory {
  static createPlugin(type) {
    const plugins = {
      minify: () => ({
        apply: (compiler) => {
          console.log('Applying minify plugin');
        },
      }),
      bundle: () => ({
        apply: (compiler) => {
          console.log('Applying bundle plugin');
        },
      }),
    };

    const plugin = plugins[type];
    if (!plugin) {
      throw new Error(`Invalid plugin type: ${type}`);
    }
    return plugin();
  }
}

module.exports = {
  plugins: [
    PluginFactory.createPlugin('minify'),
    PluginFactory.createPlugin('bundle'),
  ],
};

19.2 Vite Plugin 工厂

javascript 复制代码
const PluginFactory = {
  createPlugin(type) {
    const plugins = {
      transform: () => ({
        name: 'transform-plugin',
        transform(code) {
          return code.replace('console.log', 'console.debug');
        },
      }),
      optimize: () => ({
        name: 'optimize-plugin',
        optimize() {
          console.log('Optimizing assets');
        },
      }),
    };

    const plugin = plugins[type];
    if (!plugin) {
      throw new Error(`Invalid plugin type: ${type}`);
    }
    return plugin();
  },
};

export default {
  plugins: [
    PluginFactory.createPlugin('transform'),
    PluginFactory.createPlugin('optimize'),
  ],
};

20. 工厂模式与微前端

20.1 模块工厂

javascript 复制代码
const ModuleFactory = {
  createModule(type) {
    const modules = {
      header: () => ({
        render: () => console.log('Rendering header module'),
      }),
      content: () => ({
        render: () => console.log('Rendering content module'),
      }),
    };

    const module = modules[type];
    if (!module) {
      throw new Error(`Invalid module type: ${type}`);
    }
    return module();
  },
};

const headerModule = ModuleFactory.createModule('header');
const contentModule = ModuleFactory.createModule('content');

headerModule.render(); // Rendering header module
contentModule.render(); // Rendering content module

20.2 Qiankun 微前端工厂

javascript 复制代码
import { registerMicroApps, start } from 'qiankun';

const MicroAppFactory = {
  createApp(type, config) {
    const apps = {
      react: {
        name: 'reactApp',
        entry: '//localhost:3001',
        container: '#reactContainer',
        activeRule: '/react',
      },
      vue: {
        name: 'vueApp',
        entry: '//localhost:3002',
        container: '#vueContainer',
        activeRule: '/vue',
      },
    };

    const app = apps[type];
    if (!app) {
      throw new Error(`Invalid app type: ${type}`);
    }

    return { ...app, ...config };
  },
};

const reactApp = MicroAppFactory.createApp('react', {});
const vueApp = MicroAppFactory.createApp('vue', {});

registerMicroApps([reactApp, vueApp]);
start();

21. 工厂模式与 Node.js 中间件

javascript 复制代码
const MiddlewareFactory = {
  createMiddleware(type) {
    const middlewares = {
      logger: () => (req, res, next) => {
        console.log(`${req.method} ${req.url}`);
        next();
      },
      auth: () => (req, res, next) => {
        if (req.headers.authorization) {
          next();
        } else {
          res.status(401).send('Unauthorized');
        }
      },
    };

    const middleware = middlewares[type];
    if (!middleware) {
      throw new Error(`Invalid middleware type: ${type}`);
    }
    return middleware();
  },
};

const express = require('express');
const app = express();

app.use(MiddlewareFactory.createMiddleware('logger'));
app.use(MiddlewareFactory.createMiddleware('auth'));

app.get('/', (req, res) => res.send('Hello World'));

app.listen(3000);

22. 工厂模式与事件处理

javascript 复制代码
const EventHandlerFactory = {
  createHandler(type) {
    const handlers = {
      click: () => (event) => console.log(`Click at ${event.clientX}, ${event.clientY}`),
      keypress: () => (event) => console.log(`Key pressed: ${event.key}`),
    };

    const handler = handlers[type];
    if (!handler) {
      throw new Error(`Invalid handler type: ${type}`);
    }
    return handler();
  },
};

document.addEventListener('click', EventHandlerFactory.createHandler('click'));
document.addEventListener('keypress', EventHandlerFactory.createHandler('keypress'));

23. 工厂模式与数据模型

javascript 复制代码
const ModelFactory = {
  createModel(type, data) {
    const models = {
      user: (data) => ({
        id: data.id,
        name: data.name,
        email: data.email,
        getFullName: () => `${data.name} (${data.email})`,
      }),
      order: (data) => ({
        id: data.id,
        total: data.total,
        createdAt: data.createdAt,
        getSummary: () => `Order #${data.id}: $${data.total}`,
      }),
    };

    const model = models[type];
    if (!model) {
      throw new Error(`Invalid model type: ${type}`);
    }
    return model(data);
  },
};

const user = ModelFactory.createModel('user', {
  id: 1,
  name: 'Alice',
  email: '[email protected]',
});
const order = ModelFactory.createModel('order', {
  id: 1,
  total: 99.99,
  createdAt: '2023-01-01',
});

console.log(user.getFullName()); // Alice ([email protected])
console.log(order.getSummary()); // Order #1: $99.99

24. 工厂模式与插件系统

javascript 复制代码
const PluginFactory = {
  createPlugin(type, options) {
    const plugins = {
      logger: (options) => ({
        log: (message) => console.log(`[${options.level}] ${message}`),
      }),
      validator: (options) => ({
        validate: (data) => data.length >= options.minLength,
      }),
    };

    const plugin = plugins[type];
    if (!plugin) {
      throw new Error(`Invalid plugin type: ${type}`);
    }
    return plugin(options);
  },
};

const logger = PluginFactory.createPlugin('logger', { level: 'INFO' });
const validator = PluginFactory.createPlugin('validator', { minLength: 5 });

logger.log('System started'); // [INFO] System started
console.log(validator.validate('hello')); // true
console.log(validator.validate('hi')); // false

25. 工厂模式与配置管理

javascript 复制代码
const ConfigFactory = {
  createConfig(type) {
    const configs = {
      development: () => ({
        apiUrl: 'http://localhost:3000',
        debug: true,
      }),
      production: () => ({
        apiUrl: 'https://api.example.com',
        debug: false,
      }),
    };

    const config = configs[type];
    if (!config) {
      throw new Error(`Invalid config type: ${type}`);
    }
    return config();
  },
};

const devConfig = ConfigFactory.createConfig('development');
const prodConfig = ConfigFactory.createConfig('production');

console.log(devConfig); // { apiUrl: 'http://localhost:3000', debug: true }
console.log(prodConfig); // { apiUrl: 'https://api.example.com', debug: false }
相关推荐
dualven_in_csdn1 小时前
搞了两天的win7批处理脚本问题
java·linux·前端
你的人类朋友2 小时前
✍️【Node.js程序员】的数据库【索引优化】指南
前端·javascript·后端
小超爱编程2 小时前
纯前端做图片压缩
开发语言·前端·javascript
应巅3 小时前
echarts 数据大屏(无UI设计 极简洁版)
前端·ui·echarts
Jimmy3 小时前
CSS 实现描边文字效果
前端·css·html
islandzzzz4 小时前
HMTL+CSS+JS-新手小白循序渐进案例入门
前端·javascript·css·html
Senar4 小时前
网页中如何判断用户是否处于闲置状态
前端·javascript
很甜的西瓜4 小时前
typescript软渲染实现类似canvas的2d矢量图形引擎
前端·javascript·typescript·图形渲染·canvas
Allen Bright4 小时前
【CSS-9】深入理解CSS字体图标:原理、优势与最佳实践
前端·css
阿芯爱编程5 小时前
最长和谐子序列,滑动窗口
前端·javascript·面试