You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中实现不违反OCP的工厂模式?

如何在TypeScript中实现符合开闭原则(OCP)的工厂模式

嗨,我完全懂你的困扰——那些满是if/else或者switch的工厂示例确实让人头疼,完全违背了开闭原则的初衷。其实在TypeScript里,我们完全可以复刻Java中那种符合OCP的工厂实现,核心思路就是把产品注册逻辑和实例化逻辑解耦,让新增产品时不用修改工厂类本身。

核心思路

不再用硬编码的条件判断来匹配产品类型,而是用一个**注册表(Registry)**来存储产品类型标识与对应构造函数的映射。新增产品时,只需要向注册表中注册新的产品类,完全不需要改动工厂的核心创建逻辑。

完整实现示例

第一步:定义产品接口

首先我们需要一个所有产品都要实现的接口,保证产品的一致性:

interface Product {
  operation(): string;
}

第二步:实现具体产品类

创建几个具体的产品实现,这里以简单的示例类为例:

class ConcreteProductA implements Product {
  operation(): string {
    return "输出结果:ConcreteProductA";
  }
}

class ConcreteProductB implements Product {
  operation(): string {
    return "输出结果:ConcreteProductB";
  }
}

第三步:实现符合OCP的工厂类

这个工厂类包含注册表、注册方法和创建方法,核心逻辑完全不需要修改就能支持新产品:

class ProductFactory {
  // 私有注册表:存储产品类型标识 -> 产品构造函数的映射
  private static productRegistry: Record<string, new () => Product> = {};

  // 对外暴露的注册方法:新增产品时只需要调用这个方法
  public static registerProduct(type: string, productClass: new () => Product): void {
    ProductFactory.productRegistry[type] = productClass;
  }

  // 产品创建方法:直接从注册表取构造函数,无需条件判断
  public static createProduct(type: string): Product {
    const ProductClass = ProductFactory.productRegistry[type];
    if (!ProductClass) {
      throw new Error(`不支持的产品类型:${type}`);
    }
    return new ProductClass();
  }
}

第四步:使用工厂

注册产品并创建实例,新增产品时只需要添加注册代码即可:

// 注册已有的产品(可以在任何地方注册,比如单独的模块)
ProductFactory.registerProduct("A", ConcreteProductA);
ProductFactory.registerProduct("B", ConcreteProductB);

// 创建产品实例
const productA = ProductFactory.createProduct("A");
console.log(productA.operation()); // 输出:输出结果:ConcreteProductA

const productB = ProductFactory.createProduct("B");
console.log(productB.operation()); // 输出:输出结果:ConcreteProductB

扩展支持带参数的产品构造函数

如果你的产品类需要构造参数,只需要稍微调整工厂类的类型定义,让它支持传递参数:

// 调整后的工厂类
class ProductFactory {
  private static productRegistry: Record<string, new (...args: any[]) => Product> = {};

  public static registerProduct(type: string, productClass: new (...args: any[]) => Product): void {
    ProductFactory.productRegistry[type] = productClass;
  }

  public static createProduct(type: string, ...args: any[]): Product {
    const ProductClass = ProductFactory.productRegistry[type];
    if (!ProductClass) {
      throw new Error(`不支持的产品类型:${type}`);
    }
    return new ProductClass(...args);
  }
}

// 带参数的产品类示例
class ConcreteProductC implements Product {
  private readonly name: string;

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

  operation(): string {
    return `输出结果:ConcreteProductC,名称:${this.name}`;
  }
}

// 注册并使用带参数的产品
ProductFactory.registerProduct("C", ConcreteProductC);
const productC = ProductFactory.createProduct("C", "测试产品C");
console.log(productC.operation()); // 输出:输出结果:ConcreteProductC,名称:测试产品C

为什么符合OCP?

  • 对扩展开放:新增产品时,只需要实现Product接口,然后调用registerProduct方法注册,完全不需要修改ProductFactory的任何内部逻辑。
  • 对修改关闭:工厂的核心创建逻辑(createProduct)永远不需要改动,避免了因为修改旧代码引入bug的风险。

内容的提问来源于stack exchange,提问作者Rama Jakaria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:45:49