The mediator design pattern provides a solution to a commonly encountered scenario in web development. That is, how to maintain communication between multiple independent modules that form part of a system, such as a webpage or a user interface system, while keeping them separate and without allowing them to communicate directly.
TLDR
The mediator design pattern facilitates communication between various independent modules, known as colleagues, in a system through a common mediator. Instead of the modules interacting directly, the mediator manages requests and directs them to the appropriate module, ensuring a clean, decoupled codebase.
The Mediator Design Pattern Explained
The mediator design pattern serves as an efficient solution when you have numerous independent modules working within a system, such as parts of a webpage or a user interface system. These modules need to be kept separate and aren’t allowed to communicate directly.
These modules, which need to communicate, are known as ‘colleagues’. Communication between these colleagues is made possible through the use of a ‘mediator’. The mediator handles requests and directs them to the appropriate colleague.
To see the Mediator Design Pattern in action, we’ll consider a JavaScript implementation, where we’ll create and communicate between colleagues using a mediator.
Implementing the Mediator Design Pattern
The implementation can be broken down into the following steps:
Step 1 – Setting up the Colleague Module We start by setting up the ‘Colleague’ constructor in ‘colleague.js’. It accepts arguments of ‘id’ and an instance of the mediator, which are set as properties of the colleague instance. The Colleague constructor is extended with methods to receive and send messages. If a recipient ID is given, the message is sent to that recipient. If not, the message is broadcast to all colleagues.
javascriptCopy code// JavaScript Document
//...
var Colleague = function (id, mediator) {
this.id = id;
this.mediator = mediator;
};
Colleague.prototype.receiveMessage = function (message) {
console.log('Module', this.id, 'received message:', message);
return true;
};
Colleague.prototype.sendMessage = function (message, recipientId) {
(recipientId) ? this.mediator.send(recipientId, message) :
this.mediator.broadcast(message, this);
};
//...
Step 2 – Creating the Mediator Module Next, in ‘mediator.js’, we create the Mediator constructor, which will store all the colleagues that it will be mediating for in an array. We set up methods to register colleagues, send messages to individual colleagues, and broadcast messages to all colleagues.
javascriptCopy code// JavaScript Document
//...
var Mediator = function () {
this.colleagues = [];
};
Mediator.prototype.register = function (colleague) {
this.colleagues.push(colleague);
};
Mediator.prototype.send = function (recipientId, message) {
this.colleagues.some(function(colleague) {
if (colleague.id === recipientId) {
return colleague.receiveMessage(message);
}
});
};
Mediator.prototype.broadcast = function (message, sender) {
this.colleagues.forEach(function(colleague) {
if (colleague.id !== sender.id) {
colleague.receiveMessage(message);
}
});
};
return Mediator;
//...
Step 3 – Initializing the System In ‘init.js’, we set up variables, create new instances of the Mediator and Colleague, and send and broadcast messages.
javascriptCopy code// JavaScript Document
//...
return {
init: function() {
var mediator, colleague1, colleague2, colleague3,
Mediator = require('mediator/mediator'),
colleague = require('mediator/colleague');
mediator = new Mediator();
colleague1 = colleague.create('colleague1', mediator);
colleague2 = colleague.create('colleague2', mediator);
colleague3 = colleague.create('colleague3', mediator);
colleague1.sendMessage('Hey there', 'colleague2');
colleague2.sendMessage('Hi colleague1', 'colleague1');
colleague3.sendMessage('Hey guys!');
}
};
//...
Step 4 – Running the System In ‘main.js’, we run the mediator example using the ‘runExample’ function.
javascriptCopy code// JavaScript Document
//...
window.runExample = function (example) {
examples[example].init();
};
//...
Conclusion
The mediator design pattern is a crucial tool in the world of web development. It promotes a well-organized, decoupled system where each module works independently while still able to communicate effectively with others. Implementing the mediator design pattern in JavaScript, as shown above, allows us to ensure that every module doesn’t depend on every other module, creating a more manageable, efficient system and eliminating the possibility of a tangled mess of dependencies. Mastering the use of the mediator design pattern leads to more efficient coding practices and greatly enhances the maintainability of your codebase.