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();