diff --git a/src/data-structures/Singleton/README.md b/src/data-structures/Singleton/README.md new file mode 100644 index 00000000..c56f7063 --- /dev/null +++ b/src/data-structures/Singleton/README.md @@ -0,0 +1,47 @@ +In the provided code, we have an example of a Singleton class. A Singleton is a design pattern that restricts the instantiation of a class to a single object. It ensures that only one instance of the class exists throughout the application and provides a global point of access to that instance. + +Let's break down the code to understand how the Singleton class works: + +```javascript +class Singleton { + constructor(config) { + // Check if an instance already exists; if yes, return it + if (typeof Singleton.instance === 'object') { + return Singleton.instance; + } + + // If no instance exists, proceed to create one + this.config = config; + Singleton.instance = this; + + return this; + } +} +``` + +The Singleton class has a constructor that takes a `config` parameter. Inside the constructor, it checks if an instance of the class already exists by checking the type of `Singleton.instance`. If an instance exists, it simply returns that instance. + +If no instance exists, it proceeds to create a new instance by assigning the `config` parameter to `this.config` and setting `Singleton.instance` to the current instance (`this`). This ensures that subsequent calls to the constructor will return the same instance. + +Now, let's see how we can use this Singleton class in our JavaScript project: + +```javascript +const config = { + // configuration properties +}; + +const instance1 = new Singleton(config); +const instance2 = new Singleton(); // Since an instance already exists, it will return the existing instance + +console.log(instance1 === instance2); // Output: true +console.log(instance1.config); // Output: { /* configuration properties */ } +console.log(instance2.config); // Output: { /* configuration properties */ } +``` + +In the example above, we create two instances of the Singleton class. The first instance (`instance1`) is created with the `config` object as a parameter. The second instance (`instance2`) is created without any parameters. Since the Singleton class ensures that only one instance exists, `instance2` will be the same as `instance1`. + +We can access the `config` property of both instances, and they will have the same value because they refer to the same instance of the Singleton class. + +The Singleton pattern is often used in scenarios where we want to have a single point of access to a shared resource or when we need to ensure that only one instance of a class exists, such as managing database connections, logging systems, or application configurations. + + diff --git a/src/data-structures/Singleton/Singleton.js b/src/data-structures/Singleton/Singleton.js new file mode 100644 index 00000000..750392ec --- /dev/null +++ b/src/data-structures/Singleton/Singleton.js @@ -0,0 +1,17 @@ + +class Singleton { + constructor(config) { + // Check if an instance already exists; if yes, return it + if (typeof Singleton.instance === 'object') { + return Singleton.instance; + } + + // If no instance exists, proceed to create one + this.config = config; + Singleton.instance = this; + + return this; + } +} + + diff --git a/src/data-structures/Singleton/__test__/Singleton.test.js b/src/data-structures/Singleton/__test__/Singleton.test.js new file mode 100644 index 00000000..bf104611 --- /dev/null +++ b/src/data-structures/Singleton/__test__/Singleton.test.js @@ -0,0 +1,39 @@ +import Singleton from '../Singleton'; + +describe('Singleton', () => { + it('should create an instance of Singleton', () => { + const instance = new Singleton({ name: 'Singleton Object' }); + expect(instance).toBeDefined(); + expect(instance).toBeInstanceOf(Singleton); + }); + + it('should return the same instance for multiple instantiations', () => { + const firstInstance = new Singleton({ name: 'First Instance' }); + const secondInstance = new Singleton({ name: 'Second Instance' }); + + expect(firstInstance).toBe(secondInstance); + }); + + it('should retain the initial configuration for multiple instantiations', () => { + const firstInstance = new Singleton({ name: 'Initial Config' }); + new Singleton({ name: 'Different Config' }); + + expect(firstInstance.config.name).toBe('Initial Config'); + }); + + it('should return the same instance even when created with different parameters', () => { + const firstInstance = new Singleton({ name: 'First Config' }); + const secondInstance = new Singleton({ name: 'Second Config' }); + + expect(firstInstance.config.name).toBe('First Config'); + expect(secondInstance.config.name).toBe('First Config'); + }); + + it('should not create a new instance when a second instance is created with different parameters', () => { + const firstInstance = new Singleton({ name: 'First Config' }); + const secondInstance = new Singleton({ name: 'Second Config' }); + + expect(firstInstance).toBe(secondInstance); + expect(secondInstance.config.name).not.toBe('Second Config'); + }); +});