class Foo{
}
var instance: Foo;
export function getFooInstance(){
/* logic */
}
或
export class Foo{
private static _instance;
private constructor(){};
public getInstance(){/* logic */}
}
// Use it like this
Foo.getInstance()
我想确保该对象只有一种方式实例?除了这个还有其他建议吗?
Typescript Playground 链接:
如果你想在类中使用 getter 那么它必须是静态的:
export class Foo{
private static _instance;
private constructor(){};
public static getInstance(){/* logic */}
}
问题是,虽然编译器会强制执行这种私有可见性,但在运行时,仍然有可能绕过它,即使是无意的,例如,如果有人直接从 javascript 使用它。
如果您使用模块/命名空间强制执行它,那么您可以完全隐藏它:
使用模块:
export interface IFoo {}
class Foo implements IFoo {}
var instance: Foo;
export function getFooInstance(): IFoo {
/* logic */
return instance;
}
这是你的代码,我刚刚添加了
IFoo
接口(也被导出),这样获得实例的人就会知道接口,但不知道类。
使用命名空间:
namespace Foo {
export interface IFoo {}
class FooClass implements IFoo {}
const instance = new FooClass();
export function getInstance(): IFoo {
return instance;
}
}
在 JS 和 TypeScript 中,如果你真的只想要一个实例,为什么不通过导出对象文字来强制使用语言本身呢?
const Foo = {
doSomething() {
}
}
export default Foo;
IMO,这是遵循 KISS 的,样板数量最少,任何人都无法创建多个实例。
话虽如此,您也可以直接导出函数。请记住,模块本身可以作为您的单例。
export function doSomething() {
}
然后导入并希望将其视为一个对象,您可以使用 import *.如果函数确实属于对象并且并非都是无状态静态函数,我更喜欢第一种方法。
import * as Foo from './Foo';
Foo.doSomething();
这取决于是否有机会为单例类创建新实例。在最后一种情况下
getInstance
可以省略,类构造函数可以充当单例工厂:
class Foo {
private static _instance;
constructor(...args) {
if (Foo._instance) {
return Foo._instance;
}
// if Foo extends non-singleton class or whatever,
// super(...args);
Foo._instance = this;
};
}
可以使用任何任意类的装饰器完成同样的事情,例如:
@singleton
class Foo { ... }
由于 TypeScript 装饰器存在一些打字问题,因此应在
singleton
装饰器内部使用自定义继承代码,而不是 Singleton extends Class
:
function singleton(Class) {
function extend(sub, sup) {
for (var prop in sup)
if (sup.hasOwnProperty(prop))
sub[prop] = sup[prop];
function __() {
this.constructor = sub;
}
__.prototype = sup.prototype;
sub.prototype = new __();
};
const Singleton = <any>function (...args) {
if (Singleton._instance) {
return Singleton._instance;
}
Class.apply(this, args);
Singleton._instance = this;
}
extend(Singleton, Class);
return Singleton;
}
这可能会伤害打字,但语法保持整洁。