In this post, we will learn how to create a singleton class using Typescript.
Singleton pattern
The Singleton design pattern is a very well-known pattern used in software engineering that ensures we only have one instance, or a single instance, of a class in our application and also provides an easy way to get access to that object.
Implementation
In order to implement a Singleton class we basically need to follow these two steps:
- Make the class constructor private, preventing from using the
new
operator to create objects of that class. - Create a static method to instantiate our single instance and make it accessible through the application.
Here's a Lonely class which implements the singleton pattern:
class Lonely {
private static instance: Lonely;
private constructor() {}
static getInstance() {
if (this.instance) {
return this.instance;
}
this.instance = new Lonely();
return this.instance;
}
}
Breaking down the code:
First, we define an instance
property:
private static instance: Lonely;
This property holds the single instance of our Lonely class. It's private and static since it shouldn't be accessible from its objects (or from its only object in our singleton case).
Then, we have the constructor:
private constructor() {}
This is one of the key pieces where we make the constructor private, so if we try to instantiate new object of Lonely with const newInstance = new Lonely()
we get an error: Constructor of class 'Lonely' is private and only accessible within the class declaration.
And finally, we have the getInstance method.
static getInstance() {
if (this.instance) {
return this.instance;
}
this.instance = new Lonely();
return this.instance;
}
We don't need to name it getInstance but it's a good practice following the naming convention so it helps our code to be widely understandable.
What we must do is make it static and public, since it will be the point of access to creating the single instance of our class.
The logic is pretty simple: if we already have an instance of our class we just return it; if it's the first instantiation then we create our object calling the private constructor new Lonely()
and return it.
We could also use the Lonely
class name instead of the this
keyword:
static getInstance() {
if (Lonely.instance) {
return Lonely.instance;
}
Lonely.instance = new Lonely();
return Lonely.instance;
}
Accessing our single instance
To access the only object of our Lonely class we just need to call its getInstance method:
const l1 = Lonely.getInstance();
const l2 = Lonely.getInstance();
console.log(l1 === l2); // return true
Top comments (6)
we've been trying to get rid of this pattern since it was invented. Please just don't use it unless you are connecting to a data source (i.e: database) and need to reuse the same connection or you are implementing some sort of NullObject pattern where it makes sense to reuse that unique instance that always behaves the same way.
Singleton pattern has really niche use cases and is usually a rotting smell of poorly designed code due to ofuscating dependencies, difficulting test cases and other headaches.
Appreciate your heads up Lluís! Indeed, as with any other pattern or almost everything in software engineering, the problem is in the way they are being used, misused/abused rather. Agree that it has really niche use cases :)
Accessing our single instance :
Is this really a "1 line" way of doing the same?
Where is the definition of
Lonely
?What prevents another class from creating a second instance of
Lonely
with its own call tonew Lonely();
?In this pattern, you never export the Lonely class. The definition is omitted in the original example as well.
The problem with this pattern is the so-called Dual Package Hazard, so the pattern is best avoided in library code. github.com/GeoffreyBooth/dual-pack...
How is that better than
or if you want to have private state
Having a type is just typeof