Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript utility function to convert a class - "constructor function" into a Singleton

I have some reading about the two ways of creating a singleton in javascript - simple object literal way and another with closure technique if we want to use private variables.

I am looking to create a utility function, for example

Singleton(classname);

Whatever class - "constructor function" i pass in here as argument the Singleton method converts this class into a Singleton object, PLUS after calling the new Classname() if somebody again fires new classname() he/she gets some new Error ( "Already instantiated once, this is Singleton" );

Use case is as below -

function Circle() {this.name = "Circle";}
SingleTon(Circle);
var circle1 = new Circle(); // returns the circle instance
var circle2 = new Circle(); // throws Error "Already instantiated once, this is Singleton"

I am just trying to define the "Singleton" method here.

I have seen similar example where a getInstance method is used to get the instance like - Singleton.getInstance(Circle) etc. but I am looking for the particular question above where another programmer habitual to creating an instance in the "new" way tries to fire new Circle(); second time somewhere in his code and receives an error.

Creating a singleton this way is one problem but main problem is throwing the "Error" for which to my understanding the Circle constructor needs to be modified somewhere in the Singleton function, not sure how to accomplish this.

Is there any solution ?

Thanks in advance !!

like image 380
Anmol Saraf Avatar asked Nov 05 '12 19:11

Anmol Saraf


2 Answers

function Singleton(param){
    var count = 0, old = window[param];
    window[param] = function(){
         if(++count <= 1) return old;
         else alert('NO WAY!'); 
    }
}

You would call it as:

Singleton('Circle');

Demo: http://jsfiddle.net/maniator/7ZFmE/

Remember this only works if Circle or any other function class is in the global window namespace. Anything in any other namespace would need some more manipulation to make it work fully.

like image 86
Naftali Avatar answered Sep 29 '22 07:09

Naftali


Try this:

Circle = function () {
  if (!(this instanceof Circle)) {
    // called as function
    return Circle.singleton || (Circle.singleton = new Circle());
  }
  // called as constructor

  this.name = "the circle";
};

Now, without new operator, you get the singleton or a new one using

var mycircle = Circle();

Beware I'm using a global name for the example, you may also do

var Circle = window.Circle = function () { //...
like image 31
metadings Avatar answered Sep 29 '22 06:09

metadings