Saturday, February 24, 2007

A better Singleton pattern example

JavaScript Singleton examples are often not so correct.
In these pages for example, top Google search results, any showed code is a Singleton design pattern:


Why these examples are not good enought?


As You can see, Singleton uses a private constructor and a static public method to get a uniq object instance.

// Java example
public class Singleton {

// Private constructor suppresses generation of a (public) default constructor
private Singleton() {}

private static class SingletonHolder {
private static Singleton instance = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.instance;
}
}

In JavaScript a constructor can't be private but It should has a private variable so why we should use a public static instance property when we could have a private one?

// Singleton pattern with JavaScript
function Singleton(instance) {
if(!Singleton.getInstance) {
Singleton.getInstance = function(){
return instance;
}; instance = new Singleton;
};
}(new Singleton);

Constructor is public but it's assigned directly to have a single private instance that will be always the same everytime we call Singleton.getInstance public method.

function Me(
instance // private class instance
) {

// public static method (Singleton design pattern)
if(!Me.getInstance) {
Me.getInstance = function(){
return instance;
}; instance = new Me;
};

// generic public properties and methods

this.name = "Andrea";
this.surname = "Giammarchi";

this.whois = function(){
return this.name.concat(" ", this.surname);
};


}(new Me);


// and now try to modify instance ...
var me = Me.getInstance(),
others = new Me({name:"No", surname:"Others"}),
you = Me.getInstance();

you.constructor.prototype = {
name:"No",
surname:"Changes"
};

Me.instance = {name:"Private", surname:"Scope"};

alert([
me.whois(),
others.whois(),
you.whois()
].join("\n"));

alert(me === you && you === Me.getInstance());

The result is my name on first alert and true on second.
Is there a simple way to implement singleton with every class ? Of course :-)

Function.prototype.Singleton = function(instance){
if(!this.getInstance) {
this.getInstance = function(){
return instance;
};
};
};


function Me(){
this.name = "Andrea";
this.surname = "Giammarchi";
this.whois = function(){
return this.name.concat(" ", this.surname);
};
};
Me.Singleton(new Me);

var me = Me.getInstance();
me.blog = "webreflection";
alert(me === Me.getInstance() && me.blog === Me.getInstance().blog);



P.S. for MarCamp "fast demo": sorry guys, bad cut and paste on showed example, just add this line if You want to test the example (damn time !!!)
instance = new Singleton;

after getInstance declaration

No comments:

Post a Comment