Javascript Typescript/ES6中的单例模式的正确方式是什么?
或 我想确保对象只有一个单向实例?除此之外还有其他建议吗Javascript Typescript/ES6中的单例模式的正确方式是什么?,javascript,typescript,ecmascript-6,Javascript,Typescript,Ecmascript 6,或 我想确保对象只有一个单向实例?除此之外还有其他建议吗 为两者键入脚本:如果要在类中使用getter,则它需要是静态的: export class Foo{ private static _instance; private constructor(){}; public getInstance(){/* logic */} } // Use it like this Foo.getInstance() 问题是,虽然编译器将强制实现这种私有可见性,但在运行时,即使是
为两者键入脚本:如果要在类中使用getter,则它需要是静态的:
export class Foo{
private static _instance;
private constructor(){};
public getInstance(){/* logic */}
}
// Use it like this
Foo.getInstance()
问题是,虽然编译器将强制实现这种私有可见性,但在运行时,即使是无意中,如果有人直接从javascript使用它,仍然有可能绕过它
如果使用模块/命名空间强制执行,则可以完全隐藏它:
使用模块:
export class Foo{
private static _instance;
private constructor(){};
public static getInstance(){/* logic */}
}
这是您的代码,我刚刚添加了IFoo
接口(它也被导出),以便获得实例的人知道接口,但不知道类
使用命名空间:
export interface IFoo {}
class Foo implements IFoo {}
var instance: Foo;
export function getFooInstance(): IFoo {
/* logic */
return instance;
}
在JS和TypeScript中,如果您真的只需要一个实例,为什么不通过导出一个对象文本来强制使用语言本身呢
namespace Foo {
export interface IFoo {}
class FooClass implements IFoo {}
const instance = new FooClass();
export function getInstance(): IFoo {
return instance;
}
}
依我看,这是继KISS之后的,最少的样板文件,任何人都无法创建多个实例
也就是说,您也可以直接导出函数。请记住,模块本身可以作为您的单例
const Foo = {
doSomething() {
}
}
export default Foo;
然后导入并希望将其视为对象,您可以使用import*。如果函数确实属于对象,并且不是所有无状态静态函数,我更喜欢第一种方法
export function doSomething() {
}
这取决于是否有机会为singleton类创建新实例。在最后一种情况下,可以省略
getInstance
,类构造函数可以充当单例工厂:
import * as Foo from './Foo';
Foo.doSomething();
对于任何任意类,都可以使用decorator执行相同的操作,例如:
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
decorator中使用自定义继承代码,而不是singleton扩展类
:
@singleton
class Foo { ... }
函数单例(类){
功能扩展(sub、sup){
用于(辅助中的var prop)
if(辅助hasOwnProperty(道具))
sub[prop]=sup[prop];
函数{
this.constructor=sub;
}
__.原型=辅助原型;
sub.prototype=新的;
};
常量单例=函数(…参数){
if(单例){
返回Singleton.\u实例;
}
类。应用(本,args);
Singleton.\u instance=this;
}
扩展(单例,类);
返回单身;
}
这可能会影响键入,但语法保持整洁。旁注:JavaScript实际上不允许对实例实施限制。由于继承是在对象(原型)之间,而不是在类之间,因此始终可以创建第二个实例–
var second=Object.create(Object.getPrototypeOf(singleton))代码>。不过,是的,这比new Foo()
更麻烦。谢谢。这就是我要找的。如果我在不同的文件中多次导入Foo,它们都会引用相同的对象吗?
@singleton
class Foo { ... }
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;
}