Design Pattern in JavaScript - Part 4

Singleton design pattern

In the previous post, we discussed the benefits of a prototype pattern, why they can be helpful and when can it create problems.

Singleton Design Pattern

Singleton is a design pattern that allows us to create a single instance of class/object and use it everywhere. It’s useful in situations where we need one single instance across the system. A simple example could be a database connection pool, configuring a firebase instance and using it across apps for making API calls by importing instances.

A lot of other patterns are frequently implemented as Singletons when only one instance is needed.

Implementation

We’ll be creating an empty object Singleton as a closure, and implementing an IIFE.

var Singleton = (function () {
    var instance;

    function createInstance() {
        var object = new Object("Instance create at: " + new Date().toLocaleString());

        return object;
    }

    return {
        getInstance: function () {
            if (!instance) {
                instance = createInstance();
            }

            return instance;
        }
    };
})();

var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();

console.log(instance1); // "I was instantiated at: 03/07/2022, 13:39:38"
console.log(instance2); // "I was instantiated at: 03/07/2022, 13:39:38"

The createInstance function is responsible for creating the instance of Singleton. The getInstance method will be invoked by the Singleton object itself.

We can write above using ES6+, by default ES6 modules are singletons.

const currentDateAndTime = new Object("I am instantiated at:" + new Date().toLocaleString());
export default currentDateAndTime;

Whenever we import the above, we’ll get the same instance. Since currentDateTime object is scoped to the module, it’s guaranteed to return the same object.

Let’s discuss the pros and cons of using this pattern

Pros

  • It provides a single point of access to an instance, so maintenance is easy
  • Like module pattern, it can hide private members
  • In our implementation above, we were able to implement lazy load for instance

Cons

  • It’s difficult to do unit testing since we’ll have to keep creating instances for each test
  • In case of race conditions where two or more threads are trying to access the same resource, it is susceptible to create ≥ two instances, which defeats the whole purpose of Singleton

This post concludes this series. We discussed commonly used design patterns in JavaScript. How it can be implemented in real-life applications and what pros and cons it has.

If you liked this thread, don't forget to share! Going forward I'll be creating real-life apps to understand design patterns and what nuances it holds.