Using Class.Occlude to Create Singletons
In my last article I talk about using an instance of Events to allow for loose coupling of functionality to limit dependencies as well as the use of singletons. There was a comment at the bottom of that article that I thought worth sharing and expounding upon:
I’ve been using Class.Occlude and occluding to document.body when I need a singleton. Works like a charm. – Kris Wallsmith
I thought this was a great idea and thought I’d explain what he means for those of you perhaps unfamiliar with Class.Occlude.
What Class.Occlude Does
Class.Occlude allows you to define a class that is tied to a DOM element (as most are) and to prevent that class from creating more than one instance for that DOM element. If you created a class that, say, validated a form, and you wanted to ensure that the user (the JavaScript user – not a site visitor) of your class didn’t attach two instances of that validator to the same form twice, as doing so would result in, say, a state where it was impossible to submit the form, you could use Class.Occlude to ensure that even if two instances of the form validator were created, only one would do anything. Indeed, the second time you tried to instantiate the validator class you would just be returned the first one. Here’s what it looks like:
var FancyFormValidator = new Class({
Implements: Class.Occlude,
property: 'FancyFormValidator',
initialize: function(form) {
this.element = $(form);
if (this.occlude()) return this.occluded;
//...the rest of your awesome validation logic
}
});
var fancyValidator = new FancyFormValidator($('myform'));
var fancyValidator2 = new FancyFormValidator($('myform'));
//fancyValidator === fancyValidator2
Using Class.Occlude to Create Singletons
So what Kris does (per his comment) when he wants an instance of a class but wants to ensure that there is only ever one instance, he occludes the document body. This means that even if you try and create a new instance of that class, if you’ve already created one, you’ll be returned the existing one.
For example:
var SingleFoo = new Class({
Implements: Class.Occlude,
property: 'SingleFoo',
initialize: function(arg1, arg2, etc) {
this.element = $(document.body);
if (this.occlude()) return this.occluded;
//the rest of your stuff goes here
}
});
var foo1 = new SingleFoo(a1, a2, etc);
var foo2 = new SingleFoo(b1, b2, etc);
//foo1 === foo2
A clever solution, if you ask me.
Follow @clientcide on twitter to get notified of new posts.
To follow me personally on twitter, follow @anutron.
July 13th, 2009 at 10:48 pm
I don’t really get the last part. Can you give a document body code example?
July 13th, 2009 at 11:21 pm
@Martin – Yep. I’ve updated the post with an example.
July 14th, 2009 at 12:43 am
Ahh, I see. Thanks!
July 15th, 2009 at 12:56 am
Does your first example clas need to implement Class.Occlude?
July 15th, 2009 at 7:38 am
@adamfish oh, duh! Yeah. Nice catch. I’ve updated the example.
July 30th, 2009 at 1:04 pm
I use something like that in my application code:
var mySingletonClass = new Class(...);
mySingletonClass = new mySingletonClass;
The action just destroy the constructor of mySingletonClass, then you got a easy doin’ Singleton.
Am I wrong ?
Could this “trick” generate problem ?
Or it’s just a OOP failure ?
Thank you for this interesting post !
July 30th, 2009 at 1:37 pm
There’s no value in doing that – you could just declare your object and be done with it. The only value in making it a class is so you could extend it or implement changes into it, which your example would preclude.