user3278897
user3278897

Reputation: 1004

Javascript / Node JS best way to create singleton object

I completed my home work and got perfect result. But i just want to check , is this the best way to create singleton instances or is their any other way:

I created a singleton object using the module pattern (closures) as, "app.js"

var singleton1 = require('./singletonUser1');
console.dir(singleton1.getlocalvariable());
singleton1.setlocalvariable(20);
console.dir(singleton1.getlocalvariable());

var singleton2 = require('./singletonUser2');
console.dir(singleton2.getlocalvariable());
singleton2.setlocalvariable(30);
console.dir(singleton.getlocalvariable());

Actual singleton object (singleton.js):

var singleton = (function () {
    var localvariable = 10;

    return {
        getlocalvariable: function () {
            console.dir('This is getInstance');
            return localvariable;
        },
        setlocalvariable: function (value) {
            console.dir('This is setlocalvariable');
            localvariable = value;
        },
    };
})();

module.exports = singleton;

Then Singleton object user 1 (singletonUser1.js):

var singletonUser1 = (function () {
    var singleton = require('./singleton');

    return {
        getlocalvariable: function () {
            console.dir('This is singletonUser1---getlocalvariable');
            return singleton.getlocalvariable();
        },
        setlocalvariable: function (value) {
            console.dir('This is singletonUser1---setlocalvariable');
            singleton.setlocalvariable(value);
        },
    };
})();

module.exports = singletonUser1;

Singleton Object User 2 (singletonUser2.js)

var singletonUser2 = (function () {
    var singleton = require('./singleton');

    return {
        getlocalvariable: function () {
            console.dir('This is singletonUser2222---getlocalvariable');
            return singleton.getlocalvariable();
        },
        setlocalvariable: function (value) {
            console.dir('This is singletonUser22222---setlocalvariable');
            singleton.setlocalvariable(value);
        },
    };
})();
module.exports = singletonUser2;

Please consider that, Single User 1 and User 2, is for a purpose according to my project, the above is just an prototype to the real world problem.

My question is, I am sure this is creating a single instance of the class (As i checked using the app.js above). But is this the best way?

Upvotes: 7

Views: 8984

Answers (3)

David Rearte
David Rearte

Reputation: 874

this is my configurable singleton for a service

function AdService(name) {
    console.log('new instance created');
    this.name = name || 'defaultName';
    this.greet = function () {
        console.log('hi ' + this.name);
    }
};

function Singleton() {
    this.instance = null;
    this.getInstance = function getInstance(name) {
        if (!this.instance)
            this.instance = new AdService(name);

        return this.instance;
    }
}

var singleton = new Singleton();

module.exports = function (name) {
    return singleton.getInstance(name);
}

Upvotes: 1

mido
mido

Reputation: 25044

I find singleton class in JavaScript bit wobbly, in java it is quite clear, i.e whenever you create an object of a class, you get the same object, but in JS, (at least IMO) there is no true class to begin with.( nope, ES6 classes don't count, answer this, can you have private attributes in that?)

You code just does a closure, it might well have been the below code and made no difference:

var localvariable = 10;

function getlocalvariable() {
    console.dir('This is getInstance');
    return localvariable;
};
function setlocalvariable(value) {
    console.dir('This is setlocalvariable');
    localvariable = value;
};
module.exports = {
  getlocalvariable: getlocalvariable,
  setlocalvariable: setlocalvariable
};

that said, end of day, Singleton is just a pattern, how we implement depends on us, nothing particularly wrong with the way you did.

Edit: A singleton implementation by someone who knows JS better than me (taken from Learning JavaScript Design Patterns)

var mySingleton = (function () {

  // Instance stores a reference to the Singleton
  var instance;

  function init() {

    // Singleton

    // Private methods and variables
    function privateMethod(){
        console.log( "I am private" );
    }

    var privateVariable = "Im also private";

    var privateRandomNumber = Math.random();

    return {

      // Public methods and variables
      publicMethod: function () {
        console.log( "The public can see me!" );
      },

      publicProperty: "I am also public",

      getRandomNumber: function() {
        return privateRandomNumber;
      }

    };

  };

  return {

    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: function () {

      if ( !instance ) {
        instance = init();
      }

      return instance;
    }

  };

})();

var myBadSingleton = (function () {

  // Instance stores a reference to the Singleton
  var instance;

  function init() {

    // Singleton

    var privateRandomNumber = Math.random();

    return {

      getRandomNumber: function() {
        return privateRandomNumber;
      }

    };

  };

  return {

    // Always create a new Singleton instance
    getInstance: function () {

      instance = init();

      return instance;
    }

  };

})();


// Usage:

var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); // true

var badSingleA = myBadSingleton.getInstance();
var badSingleB = myBadSingleton.getInstance();
console.log( badSingleA.getRandomNumber() !== badSingleB.getRandomNumber() ); // true

// Note: as we are working with random numbers, there is a
// mathematical possibility both numbers will be the same,
// however unlikely. The above example should otherwise still
// be valid.

Upvotes: 0

Mihails Butorins
Mihails Butorins

Reputation: 918

var Singleton = (function(){
  function Singleton(){
    this.localVariable = 5;
  }

  // Object can have instance methods as usually.
  Singleton.prototype.getLocalVariable = function() {
    return this.localVariable;
  };

  var instance;

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


var instance1 = new Singleton();
var instance2 = new Singleton();

console.log(instance1 === instance2); // true

console.log(instance1.localVariable, instance2.localVariable); // 5 5

instance1.localVariable = 20;
console.log(instance1.localVariable, instance2.localVariable); // 20 20

console.log(instance1.getLocalVariable()); // 20

Upvotes: 5

Related Questions