Home > Software engineering >  Object of Singletons
Object of Singletons

Time:08-01

What is the best way of creating an object of Singletons? I have a class which will be shared between different applications. This class should be a singleton PER application.

Here is what I currently have. However, when I instantiate app1 twice, it creates a new instance for that.

class Sample {
  constructor(appName) { // eslint-disable-line
    if (!Sample._instance[appName]) {
      Sample._instance[appName] = this
      console.log('Creating new instance')
      this.counter = 0
    }
    return Sample._instance[appName]
  }

  getVal () {
    this.counter  
    console.log('counter: '   this.counter)
  }
}

Then I call it like this:

import Sample from './sample'


const sample1 = new Sample('app1')
sample1.getVal() // OK - prints 1
sample1.getVal() // OK - prints 2

const sample1a = new Sample('app1')
sample1a.getVal() // NOK - prints 1 - should print 3

const sample2 = new Sample('app2')
sample2.getVal() // OK - prints 1
sample2.getVal() // OK - prints 2

If instead I do something like below, then how can I actually pass in appName when the instance is created already during import?

const sample = new Sample(appName)
export default sample

CodePudding user response:

Just adding static _instance = {} got rid of the runtime error I encountered and made it work as you want.

I also tested this in nodejs to make sure there's not anything weird going on when importing the class instead of declaring it in the same file.

class Sample {
  static _instance = {};

  constructor(appName) { // eslint-disable-line
    if (!Sample._instance[appName]) {
      Sample._instance[appName] = this
      console.log('Creating new instance')
      this.counter = 0
    }
    return Sample._instance[appName]
  }

  getVal () {
    this.counter  
    console.log('counter: '   this.counter)
  }
}

const sample1 = new Sample('app1')
sample1.getVal() // OK - prints 1
sample1.getVal() // OK - prints 2

const sample1a = new Sample('app1')
sample1a.getVal() // NOK - prints 1 - should print 3

const sample2 = new Sample('app2')
sample2.getVal() // OK - prints 1
sample2.getVal() // OK - prints 2

CodePudding user response:

Differentiate the roles of the container object and the singleton.

Below I made an IIFE singleton container that handles creating and storing new instances of Sample and it returns an existing instance if it's already stored.

You can keep the class definitions and container singleton in their own file and export the container. Since it's already invoked in the module, you just need to call container.get('app') in the importing scripts.

class Sample {
  constructor() {
     console.log('Creating new instance')
     this.counter = 0
  }

  getVal () {
    this.counter  
    console.log('counter: '   this.counter)
  }
}

const container = (() => {
  const singletons = {};
  
  const get = (appName) =>{
    if (!singletons[appName]){
      singletons[appName] = new Sample();
    }
      return singletons[appName]
  }
  return { get }
})();

let sample1 = container.get('app1')
sample1.getVal();
sample1.getVal();

let sample1A = container.get('app1')
sample1A.getVal();

let sample3 = container.get('app2')
sample3.getVal();

  • Related