Support for Singletons Added
I recently received an emailed from Nicholas Barthelemy of http://www.nbarthelemy.com regarding a little method he had written for creating Singletons with my inheritance library. Using Singletons in Javascript is something I do quite frequently, but I have always thought about them in the traditional Javascript sense (more on this later). I'd like to thank Nicholas for sending his email and for sparking my interest in adding support for the more classical style of Singleton.
Now without further ado, for your coding pleasure...I introduce Class.singleton!
But first a little background...
In its most basic form, a singleton in Javascript can be written quite simply using basic object notation.
var Singleton = {
property: 'value',
someMethod: function() {
},
otherMethod: function() {
}
};
You can however get a little fancier and include some private data with your Singleton by taking advantage of closures.
var FancySingleton = (function() {
// private variables and functions
var secret = 'top secret';
function decodeSecrets() {
// ...
}
// return my public methods
return {
decrypt: function(code) {
// public functions can access private
// data and functions
return decodeSecrets(code);
}
};
})();
All this is great and you've probably seen this style of Javascript in many many locations. However, if you come from a classical inheritance background you may have noticed that this style of code more resembles a namespace, or a Ruby module, or just simply as a Class with a pile of static methods and properties. In fact, this style of Javascript can be used and is used to namespace code in many libraries current available.
In a classical pattern sense, a Singleton is a class that has at least one static method you can use to obtain the only instance of that class (See: Singleton Pattern). None of the examples previously shown have this. Class.singleton brings this classical approach back to Javascript.
In its most basic form Class.singleton
can be used just like Class.extend
(Class.create
for those Prototype-ists).
// define your App's singleton
var Application = Class.singleton({
initialize: function() {
// initializer function, called only once
this.member = 'an instance member';
},
doSomething: function() {
// ...
}
});
So far, aside from using a different method, this looks nothing different from Class.extend
. However, there are actually quite a few differences. If you tried to access any of the public methods you defined an error will be thrown by the Javascript engine.
// will not work, JS throws error
Application.doSomething();
If you were to inspect the Application object you might be a little worried since none of the methods you defined are actually attached to the Application object. In fact, it will contain only a single method getInstance
. Just like you'd expect in the classical pattern, that getInstance
function is used to obtain the only instance of Application class.
// get the instance
var app = Application.getInstance();
// will work now
app.doSomething();
I use a lazy loading technique to create the singleton instance the first time getInstance
is called. This is when the initialize function that you defined will be called.
So what happens when you want to create a Singleton that inherits behavior from a base Singleton, or any Class for that matter. Well, that's just as simple as you would think. Again the parameter format matches Class.extend
function.
// We need a better Application, that builds upon
// our existing Applications behaviours
var BetterApplication = Class.singleton(Application, {
initialize: function() {
// remember, I am called just once
// call my parent constructor
this.parent();
// initialize more members
this.newMember = 'yet another member';
},
// add more methods
doMoreThings: function() {
// ...
}
});
var better = BetterApplication.getInstance();
app.doSomething();
app.doMoreThings();
The above code will create a BetterApplication
singleton object that inherits functionality from Application
.