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

TypeScript中工厂模式引发循环依赖,求更简便解决方案

解决TypeScript工厂模式循环依赖的简便方案

针对你遇到的Circle类与工厂函数的循环依赖问题,无需复杂的接口重构或依赖注入,以下几个简便方案可快速解决:

1. 使用动态导入(延迟加载)

将Circle类中对工厂函数的静态导入改为运行时动态导入,规避编译阶段的循环引用。修改circle.ts代码如下:

// circle.ts
import { Shape } from './shape';

class Circle extends Shape {
  public type = 'circle';

  public async foo() {
    // 仅在方法执行时加载工厂函数
    const { createShapeByType } = await import('./shape-factory');
    const type = 'whatever'; // 根据实际逻辑生成类型字符串
    const shape = createShapeByType(type);
    // 后续操作shape实例
  }
}

若无需异步逻辑,在CommonJS环境下可使用同步require:

public foo() {
  const { createShapeByType } = require('./shape-factory');
  const type = 'whatever';
  const shape = createShapeByType(type);
}

2. 引入形状注册表

创建模块级注册表,让具体形状类自行注册,工厂函数从注册表中获取构造函数,彻底解除工厂与具体类的直接依赖:

第一步:创建注册表文件 shape-registry.ts

// shape-registry.ts
import { Shape } from './shape';

// 定义形状构造函数类型
type ShapeConstructor = new () => Shape;

// 存储类型与构造函数的映射
export const shapeRegistry: Record<string, ShapeConstructor> = {};

// 注册形状的方法
export function registerShape(type: string, constructor: ShapeConstructor) {
  shapeRegistry[type] = constructor;
}

第二步:修改工厂函数 shape-factory.ts

// shape-factory.ts
import { shapeRegistry } from './shape-registry';

export function createShapeByType(type: string) {
  const Constructor = shapeRegistry[type];
  if (!Constructor) {
    throw new Error(`Unknown shape type: ${type}`);
  }
  return new Constructor();
}

第三步:让具体形状类注册自身

// circle.ts
import { Shape } from './shape';
import { registerShape } from './shape-registry';

class Circle extends Shape {
  public type = 'circle';

  public foo() {
    const type = 'whatever';
    const { createShapeByType } = require('./shape-factory');
    const shape = createShapeByType(type);
  }
}

// 将Circle注册到注册表
registerShape('circle', Circle);
// triangle.ts
import { Shape } from './shape';
import { registerShape } from './shape-registry';

class Triangle extends Shape {
  public type = 'triangle';
}

registerShape('triangle', Triangle);

此方案下,工厂与具体类仅依赖注册表,循环依赖完全消除。

3. 合并工厂与基础类文件(小型项目适用)

若代码库规模较小,可将shape-factory.ts内容合并到shape.ts中,配合类型前置声明简化引用:

// shape.ts
export class Shape {
  public type = 'shape';
}

// 前置声明具体形状类
declare class Circle extends Shape {}
declare class Triangle extends Shape {}

export function createShapeByType(type: string) {
  if (type === 'circle') {
    return new Circle();
  }
  if (type === 'triangle') {
    return new Triangle();
  }
  throw new Error(`Unknown shape type: ${type}`);
}

修改circle.ts:

// circle.ts
import { Shape, createShapeByType } from './shape';

export class Circle extends Shape {
  public type = 'circle';

  public foo() {
    const type = 'whatever';
    const shape = createShapeByType(type);
  }
}

该方案适合小型项目,减少文件间的循环引用,但扩展性不如注册表方案。

内容的提问来源于stack exchange,提问作者Chenxiao Guan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:50:23