2

In Java, we have the private constructor

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;
    }
}

which makes a class can't be intantiated outside the class. Is there something like that in TypeScript?

Zhipeng YANG
  • 797
  • 9
  • 18

3 Answers3

3

I'll start with the java part, and will add one extra thing over what @DavideLorenzoMARINO wrote and that's the volatile keyword:

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;
    }
}

If you really want to make sure that this works in a multi-threaded environment then you might even want to consider the "Double Checked Locking" approach:

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;
    }
}

As for the typescript part, I don't think that this pattern works well in typescript as unlike java at runtime nothing prevents another developer from instantiating more than one instance.

If you trust the developers who work with the code then it's fine, but if not then why not just surround the instance in a module/namespace so that the implementation is hidden?

Something like:

namespace MySingleton {
    class MySingletonInstance {
        echo(value: string): string {
            console.log(value);
            return value;
        }
    }

    export var instance = new MySingletonInstance();
}

But since you'll only be having one instance of this class, then I think that in javascript it makes more sense to not use a class at all, it just make things more verbose, and you can simply:

namespace MySingleton {
    export interface MySingletonInstance {
        echo(value: string): string;
    }

    export var instance: MySingletonInstance = {
        echo: value => {
            console.log(value);
            return value;
        }
    }
}
Community
  • 1
  • 1
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
2

Something like that should work:

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;
    }

    ...
 }

Also in java is not necessary to use a lazy initialization because the singleton is not initialized if not used. A better approach:

public class Singleton {
    private static Singleton INSTANCE = new Singleton();
    private Singleton() {}

    public Singleton getInstance(){
        return INSTANCE;
    }
}

To answer to the comment of Zhipeng, a static initialization is thread safe, as defined in the JLS at 12.4.2:

The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure...


Note: the use of lazy implementation is useful only if it is possible to use some static method without using getInstance(). In this case the Singleton class is instantiated also if never used.


For a complete description on Singleton on java you can take a look on an article I wrote for Dzone

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
0

Take a look at this issue for some ideas on how you can achieve this now, but take note that TypeScript 2.0 will have private constructors and that's coming out very soon. For the time being, I recommend writing the following code...

class Singleton {
    private static instance: Singleton = new Singleton();

    // todo: mark as private when TS 2.0 comes out
    constructor() {
    }

    static getInstance() {
        return this.instance;
    }
}

...then change it to private once TypeScript 2.0 comes out.

David Sherret
  • 101,669
  • 28
  • 188
  • 178