The mediator design pattern can be very useful to decouple a group of objects. Let's see how.
Let's say we have two very simple objects. The first is an archive of numbers:
var archive = (function (){
var numbers = [];
return {
getNumbers: function (){
return archive;
},
addItem: function (number){
archive.push(number);
}
};
}());
The second object prints the sum of the numbers of the previous object:
var printsum = (function (){
return {
print: function (n){
console.log(n);
},
sum_and_print: function (archive){
var i,sum = 0;
for(i = 0;i < archive.length; i++){
sum += archive[i];
}
this.print(n)
}
};
}());
Ok. Now we need to recalculate and print the sum each time a new item is added to the archive. The first solution is straightforward:
...
addItem: function (number){
archive.push(number);
// we call directly the function
printsum.sum_and_print(archive);
}
...
This could be a solution but It has a drawback: we bind explicity the two objects together. With many objects and direct dependencies this could be very difficult to manage. Moreover, chaging or adding other dependencies could translate in changing extensively the (already tested) code.
The mediator
The mediator is an object that mediates between other objects. Instead of calling functions directly we notify events to the mediator. The mediator calls every function that is subscribed to a certain event.
Let's rewrite the example using occamsrazor.js to build a mediator:
//mediator
var pubsub = occamsrazor();
// we need 2 validators, one for the event and the second for the object
// this validate the type of the event
var is_changed_event = occamsrazor.validator(function (evt){
return evt === 'changed';
});
// this validate the type of the object
var is_archive = occamsrazor.validator(function (obj){
return 'getNumbers' in obj;
});
// the archive object
var archive = (function (){
var numbers = [];
return {
getNumbers: function (){
return numbers;
},
addItem: function (number){
numbers.push(number);
// this notify the event to the mediator
pubsub.publish('changed', this);
}
};
}());
// the printsum isn't changed
var printsum = (function (){
return {
print: function (n){
console.log(n);
},
sum_and_print: function (archive){
var i,sum = 0;
for(i = 0;i < archive.length; i++){
sum += archive[i];
}
this.print(sum);
}
};
}());
// subscribe the event
pubsub.subscribe(function (evt, archive){
printsum.sum_and_print(archive.getNumbers());
}, [is_changed_event,is_archive])
Build a mediator with occamsrazor.js has another advantage: events are notified only for the objects that pass every validator.
Next challenge: try to integrate occamsrazor.js with backbone.js
Stay tuned !