The Mediator is a behavioral design pattern in which objects, instead of communicating directly with each other, communicate only through a central message passing object (the Mediator). The Mediator pattern facilitates both loose couple and high cohesion.
Coupling measures the degree to which program modules rely on other modules. Loose coupling implies each component can operate or be tested independently of other components. Tight coupling implies each component "knows" the details or inner workings of other components. The Mediator almost entirely eliminates coupling between participating objects by becoming the only outside point of contact. All a module needs to know is how to broadcast messages through the Mediator — it doesn't matter whether 0, 1, or even 100 other modules act on those messages.
myObject.someFunction(args),
then one change in how your program works may cause a ripple
effect of changes through several modules. TL;DR:
tight coupling causes headachesCohesion is a measure of how focused a piece of code is. High cohesion implies a component's properties and methods are strongly related, and work toward one or more closely related tasks. Low cohesion implies a component may handle two or more unrelated or dissimilar tasks.
The following example was built on ideas presented by Paul Marcotte. I especially like his comparison between the Mediator pattern and the Observer pattern:
"Instead of using the Observer pattern to explicitly set many-to-many listeners and events, Mediator allows you to broadcast events globally across colleagues."
Mediator = function() {
var debug = function() {
// console.log or air.trace as desired
};
var components = {};
var broadcast = function(event, args, source) {
if (!event) {
return;
}
args = args || [];
//debug(["Mediator received", event, args].join(' '));
for (var c in components) {
if (typeof components[c]["on" + event] == "function") {
try {
//debug("Mediator calling " + event + " on " + c);
source = source || components[c];
components[c]["on" + event].apply(source, args);
} catch (err) {
debug(["Mediator error.", event, args, source, err].join(' '));
}
}
}
};
var addComponent = function(name, component, replaceDuplicate) {
if (name in components) {
if (replaceDuplicate) {
removeComponent(name);
} else {
throw new Error('Mediator name conflict: ' + name);
}
}
components[name] = component;
};
var removeComponent = function(name) {
if (name in components) {
delete components[name];
}
};
var getComponent = function(name) {
return components[name]; // undefined if component has not been added
};
var contains = function(name) {
return (name in components);
};
return {
name : "Mediator",
broadcast : broadcast,
add : addComponent,
rem : removeComponent,
get : getComponent,
has : contains
};
}();
And here's how to use it:
Mediator.add('TestObject', function() {
var someNumber = 0; // sample variable
var someString = 'another sample variable';
return {
onInitialize: function() {
// this.name is automatically assigned by the Mediator
alert(this.name + " initialized.");
},
onFakeEvent: function() {
someNumber++;
alert("Handled " + someNumber + " times!");
},
onSetString: function(str) {
someString = str;
alert('Assigned ' + someString);
}
}
}());
Mediator.broadcast("Initialize"); // alerts "TestObject initialized"
Mediator.broadcast('FakeEvent'); // alerts "Handled 1 times!" (I know, bad grammar)
Mediator.broadcast('SetString', ['test string']); // alerts "Assigned test string"
Mediator.broadcast('FakeEvent'); // alerts "Handled 2 times!"
Mediator.broadcast('SessionStart'); // this call is safely ignored
Mediator.broadcast('Translate', ['this is also safely ignored']);
I'm a Senior Culinary Software Developer at Yummly working on various front-end and middle-tier tasks, primarily using JavaScript. I blog about web design and development topics including accessibility, usability, performance, and developing HTML / CSS / JavaScript applications on Appcelerator Titanium and Adobe AIR.
If you're a web developer, you might enjoy Jelo, my JavaScript library.
All original work on this site is covered by a Creative Commons Attribution 3.0 license unless otherwise specified.
You may share or use any code or images from this site in any manner, for free, so long as reasonable effort has been made to give credit where due.
The views expressed in the posts and comments on this blog do not necessarily reflect those of my current or former employers.