在Typescript/ES6中,单例模式的正确方式是什么?
What is the right way for Singleton pattern in Typescript/ES6?
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()
我想确保只有一个方法实例的对象?除此之外,还有什么建议吗?
如果你想在类中使用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;
在我看来,这是遵循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;
}
可能会影响输入,但语法保持整洁。
相关文章:
- 在AngularJS应用程序中使用封装指令和路由的推荐方式是什么
- 在ng重复循环中显示条件内容的最佳方式是什么
- 在node.js中编写单元测试的最佳方式是什么
- 使用AJAX在Rails中提交动态表单的最佳方式是什么
- 使用Angular存储用户以前是否选中过复选框,然后再调用它的最佳方式是什么
- 在AngularJS中使用多个主题的最佳方式是什么
- 存储数据的最佳方式是什么,以便与jquery一起使用
- 为Google闭包类定义属性的首选方式是什么
- 用JavaScript随机给网页上的每个字母上色的最佳方式是什么
- 将JavaScript检测与MVC4显示模式集成的最佳方式是什么
- 正确的使用方式是什么.js与网络工作者
- 在客户端调整图像大小/裁剪图像的最佳方式是什么
- 大规模保存cookie的最佳方式是什么
- Vue.js中端到端(e2e)测试的正确方式是什么
- 在JavasciptMVC中存储常量值的最佳方式是什么
- 在angular js中,每次应用程序进入状态时,重新加载状态的最佳方式是什么
- 在项目中组织CSS/JavaScript的最佳方式是什么
- 在JavaScript中,最紧凑、最优雅、最高效的四舍五入方式是什么
- Angular:将对象存储在服务中以在视图中显示和将crud函数存储到服务器的最佳方式是什么
- Java开发人员在不编写Javascript的情况下生成Javascript的最佳方式是什么