Javascript 如何创建一个不能在TypeScript外部实例化的类?
在Java中,我们有私有构造函数Javascript 如何创建一个不能在TypeScript外部实例化的类?,javascript,typescript,Javascript,Typescript,在Java中,我们有私有构造函数 public class Singleton{ private static volatile Singleton INSTANCE = null; private Singleton(){ } public static Singleton getInstance(){ if(INSTANCE == null){ synchronized(Singleton.class){
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中有类似的东西吗?类似的东西应该可以:
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;
}
}
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;
}
}
为了回答智鹏的评论,静态初始化是线程安全的,如JLS中的定义:
Java虚拟机的实现负责使用以下过程进行同步和递归初始化
注意:只有在可以使用某些静态方法而不使用getInstance时,使用惰性实现才有用。在这种情况下,如果从未使用过,也会实例化Singleton类
有关java上的Singleton的完整描述,请参阅我为撰写的一篇文章,了解如何实现这一点,但请注意,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发布后将其更改为private。我将从java部分开始,并将在@DavidorenZomarino编写的内容上添加一个额外的内容,即:
如果你真的想确保它在多线程环境中工作,那么你甚至可能要考虑这样的方法:
public class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {}
public Singleton getInstance(){
return 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;
}
}
至于typescript部分,我认为这个模式在typescript中并不好用,因为与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;
}
}
}
但是,如果单例是在Java的多线程环境中呢?它会崩溃吗?静态初始化是线程安全的,这是由designI授予的。我在官方文档中添加了一个链接,解释静态初始化器是如何线程安全的。谢谢。TypeScript中的另一个问题:因为在构造函数中,它将抛出异常。那么,在使用新的Singleton调用它时,它会导致问题吗?