DEV Community

Cover image for Singleton - JavaScript Design Patterns
İnanç Akduvan
İnanç Akduvan

Posted on • Edited on

Singleton - JavaScript Design Patterns

Hey my friend,
it will be easy to follow, don't scare, stay with me. 👻

Let's start by summarizing what a Design Pattern is.


What is a Design Pattern?

Design patterns are solutions to solve our common and recurring problems.

We all develop and face problems everyday and many of them are generally similar to each other. These patterns are born to solve these common problems.

Surely, you can accept them as a guide and customize them to satisfy your needs specifically in your project.

In this article, we will talk about 'Singleton' which is only one of the design patterns.


Singleton

The only and most important sentence about this design pattern is that:

You can have only one instance of a class created as a Singleton.

If a class is singleton,
-- You can only have one instance of it,
-- You can share it everywhere in your project and reach your global and common values everywhere.

So, how is this useful?
Let's code an example together and see how we can use this pattern.

For example, we can create a very simple state management for our application with Singleton.

Let's do it and create a regular class named 'State':

class State {
    constructor(states) {
        this.states = states;
    }

    getState(stateName) {
        return this.states[stateName];
    }

    updateState(stateName, newValue) {
        this.states[stateName] = newValue;
    }
}

const appStates = new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
});
Enter fullscreen mode Exit fullscreen mode

1) We created a class named 'State'.
2) Our class has an initial object named 'states'. This object includes initial values of our states.
3) Our class also has a method named 'getState' to get value of a targetted state.
4) It also has a method named 'updateState' to update value of a targetted state.
5) We created an instance of our class and assigned it to a variable named 'appStates'.

Well, it is okay. But this is not singleton yet, right?
We can simply create one more instance of this class, just like:

const appStates = new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
});

const appStates2 = new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
});
Enter fullscreen mode Exit fullscreen mode

BUT NO, we don't want this! We need only one appState, so we can control it safely everywhere in the project. We want to prevent creating instances more than one. It is the one! ❤️

Let's add one more code line and it will allow to have only one instance:

let isAppStateInstanceCreated = false;

class State {
    constructor(states) {
        if (isAppStateInstanceCreated) {
            throw new Error("You are allowed to have only one appStates!");
        }

        isAppStateInstanceCreated = true;

        this.states = states;
    }

    getState(stateName) {
        return this.states[stateName];
    }

    updateState(stateName, newValue) {
        this.states[stateName] = newValue;
    }
}

const appStates = new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
});

const appStates2 = new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
});
// Error: You are allowed to have only one appStates!
Enter fullscreen mode Exit fullscreen mode

We created a global variable named 'isAppStateInstanceCreated' which is false as default. In the constructor of our State class, we set it to true. If true, this means that we initialized this class before. So user will get an error in this case, like 'You are allowed to have only one appStates!'

Now, State class is a Singleton.

Example usage:

appStates.updateState("onlineUsersTotal", 1300);

const currentOnlineUsersTotal = appStates.getState("onlineUsersTotal");

console.log(currentOnlineUsersTotal);
// 1300
Enter fullscreen mode Exit fullscreen mode

Extra

Stay with me one more second, it will be worth it!

We have pretty much a singleton class.
However, to be honest, we still are not safe enough.
Because, you know, we can manipulate our Class just like a regular object. Let me show you:

appStates.states = null;
Enter fullscreen mode Exit fullscreen mode

I just easily set all states to null...
No man, we cannot allow this.
We will use Object.freeze method to protect our class from this kind of effects.

const appStates = Object.freeze(new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
}));
Enter fullscreen mode Exit fullscreen mode

And now, nobody can manipulate our Class, my friend, NOBODY!
If you don't believe me, I dare you, try and see it 👊


Please don't hesitate to give feedback, correct me, contribute, comment and contact me 🤓

And if you find it useful, please,
like and share ❤️

Follow me on:

Github: https://github.com/inancakduvan/
Twitter: https://twitter.com/InancAkduvan

Thank you for coming with me until end of the reading! 🙂

Top comments (2)

Collapse
 
artxe2 profile image
Yeom suyun

I don't understand why we should use the singleton pattern in JavaScript.
The singleton pattern enables dependency injection, which makes code easier to maintain.
However, I have rarely seen dependency injection being used in JavaScript, except in Nestjs.

Collapse
 
inancakduvan profile image
İnanç Akduvan

Hey yeom,
I generally use it when I need to manage, centralize and globalize a dataset throughout whole application. However, I agree with you that it has seen rarely.