Generics 在泛型Typescript类中实现单例
我有一个泛型类型,它将作为事件系统中事件的基类。我们期望这些参数是单例的,但它也是泛型的,这样子类就可以在事件触发时指定它们在回调中期望的参数类型 我所拥有的是这样的:Generics 在泛型Typescript类中实现单例,generics,design-patterns,typescript,singleton,Generics,Design Patterns,Typescript,Singleton,我有一个泛型类型,它将作为事件系统中事件的基类。我们期望这些参数是单例的,但它也是泛型的,这样子类就可以在事件触发时指定它们在回调中期望的参数类型 我所拥有的是这样的: export interface IEvent { } export interfact IEventArg { } export abstract class Event<TEvent extends IEvent, TEventArg extends IEventArg> implements IMessage
export interface IEvent { }
export interfact IEventArg { }
export abstract class Event<TEvent extends IEvent, TEventArg extends IEventArg> implements IMessageHandler {
private static s_instance : any;
private static s_isInitializing : boolean;
constructor() {
if (!Event.s_isInitializing)
throw new Error ("Use the GetInstance method to get this class instance.");
}
public static GetInstance<TEvent extends IEvent, TEventArg extends IEventArg>(type: { new() : T; }) : TEvent {
if (!s_instance) {
s_isInitializing = true;
s_instance = new type();
s_isInitializing = false;
}
return s_instance;
}
}
export class SelectionEvent extends Event<SelectionEvent, EmptyEventArg> {
...
}
var event = SelectionEvent.GetInstance(SelectionEvent);
导出接口事件{}
导出接口IEventArg{}
导出抽象类事件实现IMessageHandler{
私有静态s_实例:任意;
私有静态s_初始化:布尔;
构造函数(){
如果(!Event.s_正在初始化)
抛出新错误(“使用GetInstance方法获取该类实例。”);
}
公共静态GetInstance(类型:{new():T;}):TEvent{
如果(!s_实例){
s_i初始化=真;
s_实例=新类型();
s_i初始化=错误;
}
返回s_实例;
}
}
导出类SelectionEvent扩展事件{
...
}
var event=SelectionEvent.GetInstance(SelectionEvent);
这里有些事情我觉得奇怪,主要是因为打字语言的要求。GetInstance的参数似乎是必需的,因为TypeScript似乎不允许使用var x=new TEvent()
。空接口有助于强制执行可以接受为泛型类型的内容
这里似乎不起作用的是静态变量和泛型类型的组合。GetInstance方法中的块是我想要做的,但显然它没有编译。我还担心静态实例变量不会在每个事件中创建一次,而是在每个事件实例中创建一次,因此会被覆盖
在C#中,泛型类的每个实例化(类型参数集)都有自己的静态成员集。这意味着您可以编写一个单例模式,其中一个实例用于Foo
,另一个实例用于Foo
,依此类推。这是可能的,因为泛型是在运行时显示的——运行时系统实际上知道泛型是什么,并且可以为每个类型实例化分配新对象。此外,类的静态端可以引用该类的类型参数(这是运行时语义的结果)
在TypeScript中,情况并非如此。每个类只有一个构造函数,泛型或其他。这意味着类的静态端无法“查看”泛型类型参数,因为对于具有静态成员y
的任何类X
,只有一个运行时插槽用于X.y
类的单例模式通常不适合TypeScript;看见我认为您在这里有一些进展,因此如果没有关于您的用例的更多信息,我不能推荐任何具体的替代方案(可能会发布一个单独的问题)
此外,TypeScript中不应该有空接口。类型在结构上是比较的,因此任何两个空类型都是兼容的,并且您可以将任何内容分配给类型为空接口的变量。好的,这就是我所关心的。我想我可能有一个替代实现的想法,我会尝试一下,并可能发布一个单独的问题。谢谢对于具有不同名称且没有类型参数的派生类(泛型单例)是否也存在相同的情况?我假设这是作为与派生类不同的类处理的。所以,当有一个泛型版本时,每次需要一个不同的单例时,都需要创建一个空的派生类,但可以重用泛型单例代码。不是说应该这样做,只是好奇这是否可行。