I have been building some pretty large apps lately and I found the need for the registry design pattern in some of my javascript. I went with this approach because I wanted to minimize the power my objects had, yet I needed some kind of blackboard where all objects could check and report to.
In addition I found that implementing events onto the class made for a very effective event handler as well.
var Registry = new Class({ Implements : [Events], conf : {}, set : function(path,value){ var fragments = path.split('/'); if( fragments.shift() !== '') return false; // remove empty, first component if(fragments.length > 0 && fragments[fragments.length - 1] == '') fragments.pop(); var obj = {}; var ref = obj; var len = fragments.length; if( len > 0){ for(i = 0; i < len-1; i++){ ref[fragments[i]] = {}; ref = ref[fragments[i]]; } ref[fragments[len-1]] = value; this.conf = $merge(this.conf,obj); } else { this.conf = value; } }, get : function(path){ var fragments = path.split('/'); if( fragments.shift() !== '') return null; if(fragments.length > 0 && fragments[fragments.length -1] == '') fragments.pop(); var ref = this.conf; var path_exists = true; var i = 0; var len = fragments.length; while(path_exists && i < len){ path_exists = path_exists && (ref[fragments[i]] !== undefined); ref = ref[fragments[i]]; i++; } return ref; } });
The class is pretty simple but it provides for a powerful hierarchical syntax. Only two methods are supplied ‘get’ and ’set’.
Example:
var reg = new Registry(); reg.set('/Options/Default',{'name' : 'test', 'version' : 1}); reg.set('/Options/Default/name', 'changed'); reg.set('/dynamically/creates/nested/objects', true); reg.get('/Options/Default'); /* returns { name : 'changed', version : 1 } */ reg.get('/Options/Default/version'); // returns 1 reg.get('/'); /* returns { Options : { Default : { name : 'changed', version : 1 } }, dynamically : { creates : { nested : { objects : true } } } } */
I found it extremely useful for configuration objects for classes that were initialized in a tree fashion. It also seemed to help with the readability and organization of code. I also had several places where I had multiple objects doing completely different things to the same Request.JSON result. With this class I just stored it in a single place and fired off my event. I found it extremely useful to use the class as a global event manager for cases such as this. I ended up using a dot notation naming convention for my events which helped greatly in documentation and API design.
reg.addEvent('App.initialize',function(){}); reg.addEvent('App.shutdown',function(){}); reg.addEvent('Data.feed1.loaded',function(){}); reg.fireEvent('App.shutdown');
In my actual production code I had my Registry class implement my Singleton Class Mutator. This way I could initialize the registry object multiple times in my code without the need to worry about scope.