在Java中,我们有私有构造函数
public class Singleton{
private static volatile Singleton INSTANCE = null;
private Singleton(){ }
public static Singleton getInstance(){
if(INSTANCE == null){
synchronized(Singleton.class){
if(INSTANCE == null){
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
这使得类不能在类之外进行初始化。TypeScript 中有类似的东西吗?
我将从java部分开始,并将在@DavideLorenzoMARINO写的内容上添加一件额外的东西,那就是volatile
关键字:
class MySingleton {
private static volatile MySingleton instance;
private MySingleton() {
// do what ever
}
public static MySingleton getInstance() {
if (MySingleton.instance == null) {
MySingleton.instance = new MySingleton();
}
return MySingleton.instance;
}
}
如果您真的想确保这在多线程环境中有效,那么您甚至可能需要考虑"双重检查锁定"方法:
class MySingleton {
private static volatile MySingleton instance;
private MySingleton() {
// do what ever
}
public static MySingleton getInstance() {
if (MySingleton.instance == null) {
synchronized (MySingleton.class) {
if (MySingleton.instance == null) {
MySingleton.instance = new MySingleton();
}
}
}
return MySingleton.instance;
}
}
至于打字稿部分,我认为这种模式在打字稿中效果不佳,因为与运行时的 java 不同,没有什么可以阻止另一个开发人员实例化多个实例。
如果您信任使用代码的开发人员,那很好,但如果不是,那么为什么不将实例括在模块/命名空间中以便隐藏实现呢?
像这样:
namespace MySingleton {
class MySingletonInstance {
echo(value: string): string {
console.log(value);
return value;
}
}
export var instance = new MySingletonInstance();
}
但是由于你只会有一个类的实例,那么我认为在javascript中根本不使用类更有意义,它只会让事情变得更加冗长,你可以简单地:
namespace MySingleton {
export interface MySingletonInstance {
echo(value: string): string;
}
export var instance: MySingletonInstance = {
echo: value => {
console.log(value);
return value;
}
}
}
这样的事情应该有效:
class Singleton {
private static _instance:Singleton = new Singleton();
constructor() {
if (Singleton._instance){
throw new Error("Error: use getInstance()");
}
Singleton._instance = this;
}
public static getInstance():Singleton {
return Singleton._instance;
}
...
}
同样在 java 中不需要使用延迟初始化,因为如果不使用单例,则不会初始化。更好的方法:
public class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public Singleton getInstance(){
return INSTANCE;
}
}
为了回答 Zhipeng 的评论,静态初始化是线程安全的,如 JLS 12.4.2 中所定义的那样:
Java 虚拟机的实现负责使用以下过程来处理同步和递归初始化...
注意:仅当可以使用某些静态方法而不使用 getInstance() 时才使用惰性实现才有用。在这种情况下,如果从未使用过,也会实例化 Singleton 类。
有关Java上的Singleton的完整描述,您可以查看我为Dzone撰写的一篇文章。
看看这个问题,了解一些关于你现在如何实现这一目标的想法,但请注意,TypeScript 2.0 将有私有构造函数,而且很快就会出现。目前,我建议编写以下代码...
class Singleton {
private static instance: Singleton = new Singleton();
// todo: mark as private when TS 2.0 comes out
constructor() {
}
static getInstance() {
return this.instance;
}
}
。然后在 TypeScript 2.0 发布后将其更改为私有。