简化 TypeScript 中的依赖注入:深入了解 `singleton-factory-ts`
I’m happy to translate the article for you, but I’ll need the full text of the post (the parts you’d like translated). Could you please paste the article’s content here? Once I have it, I’ll provide a Simplified‑Chinese translation while keeping the source link, formatting, markdown, and code blocks unchanged.
核心概念:Singleton 与 SingletonFactory
在 singleton-factory-ts 的核心有两个主要组件:
- 一个抽象的
Singleton基类,供你的服务继承。 - 一个
SingletonFactory(它本身也是单例),负责解析依赖、管理缓存,并检测诸如循环依赖等架构缺陷。
与其在容器中手动注册服务,不如让类通过静态 getter 声明自己的依赖。
清晰、声明式的使用
该库的开发者体验非常直接。下面是一个典型的单例及其关系的定义:
import { Singleton, SingletonClassType } from 'singleton-factory-ts';
// A base singleton with no dependencies
class S1 extends Singleton {
doSomething() {
console.log("S1 is working!");
}
}
// A singleton that depends on S1
class S2 extends Singleton {
// 1. Declare dependencies declaratively
static get Dependencies(): [SingletonClassType] {
return [S1];
}
// 2. The factory will automatically inject S1 here
constructor(protected _s1: S1) {
super();
}
execute() {
this._s1.doSomething();
}
}
// 3. Access the instance effortlessly
const s2 = S2.instance;
s2.execute();
当你访问 S2.instance 时,基类 Singleton 会拦截该调用并委托给 SingletonFactory。工厂读取 Dependencies 数组,递归地构建(或获取)所需的实例,并将它们注入到 S2 的构造函数中。
深入内部:是什么让它如此稳健?
智能令牌缓存
每个继承自 Singleton 的类都会自动获得一个使用 Symbol.for(this.className) 生成的 InjectorToken。SingletonFactory 维护一个包含这些令牌的 Map(_singletonCache)。如果实例已经存在,它会返回缓存的版本,从而保证整个应用程序中真正的单例行为。
循环依赖检测
循环依赖(例如,服务 A 依赖服务 B,而服务 B 又依赖服务 A)会导致无限循环。在实例化过程中,工厂会将该类的 InjectorToken 添加到 _initializingClasses 集合中。如果在解析依赖树时遇到已经存在于该集合中的令牌,就会抛出描述性的错误:Circular dependency detected for token…。
通过 create 方法进行自定义实例化
有时标准的 new Constructor(...) 模式不足——比如需要异步操作或自定义工厂逻辑。库在 Object 和 Object.prototype 上加入了受 Objective‑C 启发的 respondsToSelector polyfill。当 SingletonFactory 解析依赖时,它会检查类是否 respondsToSelector("create")。如果是,则调用 Class.create!(...deps) 而不是构造函数,从而提供极大的灵活性。
实际采用:@greeneyesai/api-utils
该模式不仅是实验性的;它已在生产环境中积极使用。
@greeneyesai/api-utils 采用了这种单例‑工厂架构的变体来管理其内部生命周期和服务依赖。
通过利用该模式,库确保核心客户端、配置管理器和日志服务能够延迟实例化、可靠地共享状态,并在不引入笨重的依赖注入框架的情况下强制执行依赖契约。
结论
对于希望在保持严格类型安全和模块化的同时解耦 TypeScript 类的开发者,singleton-factory-ts 提供了一个简洁的蓝图。通过将声明式的静态 Dependencies 数组与智能的集中工厂相结合,它在轻量且易读的包中提供了企业级的依赖注入(DI)能力。
无论是直接导入该库,还是为诸如 @greeneyesai/api-utils 等工具适配其架构变体,singleton factory 模式仍然是任何 TypeScript 开发者工具箱中的强大补充。