Singleton - JavaScript Design Patterns
Tags: javascript, designpatterns, frontend, webdev
Published: 2023-10-14 09:08:56

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_**':
``` javascript
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
});
```

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:
``` javascript
const appStates = new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
});

const appStates2 = new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
});
```
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:
``` javascript
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!
```
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:
``` javascript
appStates.updateState("onlineUsersTotal", 1300);

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

console.log(currentOnlineUsersTotal);
// 1300
```

-----------------

## 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:

```javascript
appStates.states = null;
```
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.

```javascript
const appStates = Object.freeze(new State({
    onlineUsersTotal: 1200,
    isUserLoggedIn: true
}));
```
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! 🙂