Implementation of Singleton Method Design Pattern in JavaScript

Problem Statement:

Implement a Singleton pattern in JavaScript, ensuring that only one instance of a class is created and providing a mechanism to access that instance. Additionally, prevent cloning and serialization of the Singleton instance.

Step wise explaination of above Problem Statement

  • Immediately Invoked Function Expression (IIFE):The pattern uses an IIFE to create a closure, providing a private scope for the instance variable and functions within it.
  • Private Instance Variable: The instance variable is used to store the single instance of the Singleton class. It’s private to the closure, preventing direct access from outside.
  • Private Constructor: The Singleton constructor is defined inside the closure and checks if an instance already exists. If it does, it throws an error to prevent the creation of additional instances.
  • Static getInstance Method: The getInstance method is a static method of the Singleton class, providing a way to access the single instance. If the instance doesn’t exist, it creates a new one; otherwise, it returns the existing instance.
  • Clone and Deserialize Prevention: The clone and customDeserialize methods are defined to throw errors, preventing cloning and deserialization of the Singleton instance.
  • JSON Serialization Prevention: The toJSON method is overridden to return a JSON string with a marker property (__isSingleton). This marker is later used in the revive function to identify the Singleton instance during deserialization.
  • Reviver Function for Deserialization: The revive function is used as the reviver function for JSON.parse to check for the marker property and return the existing instance, preventing the creation of a new instance during deserialization.

Overall Code for Above Problem Statement in JavaScript:

Javascript
const Singleton = (function () {
 let instance;

 function Singleton() {
    if (instance) {
      throw new Error("Singleton instance already exists. Use getInstance method.");
    }
    // Initialization code
    this.data = Math.random(); // Example: Initialization with random data
  }

 Singleton.getInstance = function () {
    if (!instance) {
      instance = new Singleton();
    }
    return instance;
  };

 Singleton.prototype.clone = function () {
    throw new Error("Cloning of singleton instance is not allowed.");
  };

 Singleton.prototype.customDeserialize = function () {
    throw new Error("Deserialization of singleton instance is not allowed.");
  };

  // JSON.parse reviver function to prevent deserialization
 function revive(key, value) {
    if (key === '' && value && value.__isSingleton) {
      return instance;
    }
    return value;
  }

 Singleton.prototype.toJSON = function () {
    return JSON.stringify({ __isSingleton: true, data: this.data });
  };

  return Singleton;
})();

// Usage
try {
  const singletonInstance1 = Singleton.getInstance();
  console.log(singletonInstance1);

  // Attempting to create another instance should throw an error
  const singletonInstance2 = new Singleton();
} catch (error) {
  console.error(error.message); // Singleton instance already exists. Use getInstance method.
}

// Cloning prevention
try {
  const clonedInstance = Object.create(singletonInstance1);
  console.log(clonedInstance); // Will throw an error
} catch (error) {
  console.error(error.message); // Cloning of singleton instance is not allowed.
}

// Serialization prevention
try {
  const serializedInstance = JSON.stringify(singletonInstance1);
  console.log(serializedInstance); // Will throw an error
} catch (error) {
  console.error(error.message); // Serialization of singleton instance is not allowed.
}

// Deserialization prevention
const jsonString = JSON.stringify(singletonInstance1);
const deserializedInstance = JSON.parse(jsonString, revive);
console.log(deserializedInstance); // Will be the same instance as singletonInstance1

Output:

Singleton instance already exists. 
singletonInstance1 is not defined
singletonInstance1 is not defined


Singleton Method Design Pattern in JavaScript

Singleton Method or Singleton Design Pattern is a part of the Gang of Four design pattern and it is categorized under creational design patterns. It is one of the most simple design patterns in terms of modeling but on the other hand, this is one of the most controversial patterns in terms of complexity of usage.

Important Topics for the Singleton Method Design Pattern in JavaScript

  • What is Singleton Method Design Pattern in JavaScript?
  • When to use the Singleton Method Design Pattern in JavaScript?
  • Key Component of Singleton Method Design Pattern in JavaScript:
  • Implementation of Singleton Method Design Pattern in JavaScript
  • Use Case of Singleton Method Design Pattern in JavaScript
  • Advantage of Singleton Method Design Pattern in JavaScript:
  • Disadvantage Of Singleton Method Design Pattern in JavaScript

Similar Reads

1. What is Singleton Method Design Pattern in JavaScript?

Singleton pattern is a design pattern which restricts a class to instantiate its multiple objects. It is nothing but a way of defining a class. Class is defined in such a way that only one instance of the class is created in the complete execution of a program or project....

2. When to use the Singleton Method Design Pattern in JavaScript?

Here are some situations in JavaScript where the Singleton pattern may be applicable:...

3. Key Component of Singleton Method Design Pattern in JavaScript:

...

4. Implementation of Singleton Method Design Pattern in JavaScript

Problem Statement:...

5. Use Case of Singleton Method Design Pattern in JavaScript

There is a application of singleton pattern like cache-memory, database connection, drivers, logging. Some major of them are :-...

6. Advantages of Singleton Method Design Pattern in JavaScript:

The Singleton method design pattern has several benefits:...

7. Disadvantages Of Singleton Method Design Pattern in JavaScript

The Singleton Method Design Pattern have different disadvantage:...

Contact Us