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
相关产品推荐
相关产品推荐

