Husam Ajour
Husam's Blog

Husam's Blog

Node.js Design Patterns | Singleton Pattern

Node.js Design Patterns | Singleton Pattern

Husam Ajour's photo
Husam Ajour
·Nov 9, 2021·

3 min read

Introduction

Hello and welcome to the Node.js Design Patterns series! In this series, I'll be writing about pattern designs in software development using Node.js, the pros and cons of each pattern, and some examples on where each pattern can be helpful and where it can be not. ​

in this article, we'll talk about the Singleton Pattern as the first design pattern in this series.

Definition

The Singleton pattern is a creational design pattern that limits the instance creation of a class to a single instance while making sure it is accessible globally in the application.

As we can tell from the name of this pattern, it is helpful when you only need one single instance in the application. For example, this pattern can be very useful to create a logger class that logs and stores all the API call results:

class Logger {
  constructor() {
    this.log = [];
  }

  get log() {
    return this.log;
  }

  get count() {
    return this.log.length;
  }

  store(result) {
    this.log.push(result);
  }

  log(result) {
    console.log(result);
    this.store(result);
  }
}

The classical implementation of the Singleton pattern can be done by using the get instance method, and then check if there's in an existing instance or not and return that instance if exists or create an instance and then return it:

class Singleton {

  constructor() {
      if (!Singleton.instance) {
          Singleton.instance = new Logger();
      }
  }

  getInstance() {
      return Singleton.instance;
  }

}

module.exports = Singleton;

There is an easier and shorter way to do this in JavaScript; instead of creating a singleton class, all we need to do is to export a new instance instead as follows:

module.exports = new Logger();

When we run the Logger class file, it will create an instance of the Logger class, and save it in the cache, and Node.js will automatically handle exporting the same instance of the Logger to every other module that needs to use it. The full code looks as follows:

class Logger {
  constructor() {
    this.log = [];
  }

  get log() {
    return this.log;
  }

  get count() {
    return this.log.length;
  }

  store(result) {
    this.log.push(result);
  }

  log(result) {
    console.log(result);
    this.store(result);
  }
}

module.exports = new Logger();

Pros and Cons

Singleton doesn't solve all the problems in software development, as it could be very useful, it could also be overused.

Pros:

  • It provides a single point of access to a particular instance, so it is easy to maintain.
  • It gets created exactly when it is needed.
  • It is very helpful when a resource needs to be shared by the entire application.

Cons:

  • Violates the SRP "Single Responsibility Principle" by virtue of the fact that they control their creation and lifecycle.
  • Causes issues in unit testing because each unit test should be independent of the other.
  • It could be very tricky to troubleshoot, so it requires some attention when used.

Credit:

This article is written based on my understanding of the course Node.js: Design Patterns by Alex Banks

 
Share this