In these pages for example, top Google search results, any showed code is a Singleton design pattern:
- A (Re)-Introduction to JavaScript, shows a "strange" function that's not Singleton
- Matías Giovannini shows a public static instance that doesn't rappresent Singleton
- Means Nothing talks about functions, not about Singleton
- Webreference shows a static public instance again, using underscore as "__" prefix and suffix ... but doesn't show a Singleton
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
Now, how can we imlpement an observer pattern? :)
ReplyDeleteI'm not a pro in javascript, but as far as i see, your singleton pattern is not so right. The examples from other websites that you said they were wrong, seem to me more right than your implementation of the singleton pattern.
ReplyDeletechris, I accept any kind of comments, but I prefer those constructive. Any better example?
ReplyDeleteWhat about that?
ReplyDeletevar Singleton = (function() {
var instance = null;
return function() {
if (instance == null) {
// initialize instance
}
return instance;
}
})();
/*
ReplyDeleteThis is my implementation of the singleton pattern from Head First - Design Patterns. One thing that people always forget in their singleton patterns is to also implement the lazy-instanciation, which might be important in case of resource intensive objects.
*/
var Singleton = (function(){
var _instance = null;
return {
getInstance:function(){
if (!_instance)
_instance = (function(){
var _name = 'Supertone';
return {
sayName:function(){
alert('I am ' + _name + '!');
}
}
})();
return _instance;
}
}
})();