What is the JavaScript Mediator Pattern?
The Mediator Pattern is a behavioral design pattern that promotes loose coupling between objects by using a mediator object to control communication between them. In other words, the Mediator Pattern allows objects to communicate with each other indirectly through a mediator object, rather than directly with each other. This pattern is used to simplify complex relationships between objects, making the code more modular and easier to maintain.
Simple Implementation of Mediator Patterns in JavaScript
In JavaScript, the Mediator Pattern can be implemented in several ways. Here we will discuss two examples of how to implement the Mediator Pattern in JavaScript.
To illustrate and explain the mediator pattern in JavaScript, we will implement the Mediator Pattern using a mediator object that controls communication between two objects.
class Mediator {
constructor() {
this.colleague1 = null;
this.colleague2 = null;
}
setColleague1(colleague) {
this.colleague1 = colleague;
}
setColleague2(colleague) {
this.colleague2 = colleague;
}
send(message, colleague) {
if (colleague === this.colleague1) {
this.colleague2.receive(message);
} else {
this.colleague1.receive(message);
}
}
}
class Colleague {
constructor(mediator) {
this.mediator = mediator;
}
send(message) {
this.mediator.send(message, this);
}
receive(message) {
console.log(`Message received: ${message}`);
}
}
const mediator = new Mediator();
const deepak = new Colleague(mediator);
const femi = new Colleague(mediator);
mediator.setColleague1(deepak);
mediator.setColleague2(femi);
deepak.send("Hello from Deepak!");
femi.send("Hello from Femi!");
Output
Message received: Hello from Deepak!
Message received: Hello from Femi!
In this example, we have a Mediator class that controls communication between two Colleague objects. The Mediator class has two methods for setting the Colleague objects and a method for sending a message to the other Colleague object. The Colleague class has a reference to the mediator object and methods for sending and receiving messages. Finally, we create a mediator instance, two colleague instances, set the colleague objects on the mediator, and send messages between the colleagues using the send method on the colleague objects.
Implement Mediator Pattern using Event Bus
An event bus is a common way to implement the Mediator pattern in JavaScript. The event bus acts as the mediator, allowing objects to publish and subscribe to events. Here's an example:
// Define the event bus
const EventBus = (() => {
const events = {};
const subscribe = (eventName, fn) => {
events[eventName] = events[eventName] || [];
events[eventName].push(fn);
};
const unsubscribe = (eventName, fn) => {
if (events[eventName]) {
for (let i = 0; i < events[eventName].length; i++) {
if (events[eventName][i] === fn) {
events[eventName].splice(i, 1);
break;
}
}
}
};
const publish = (eventName, data) => {
if (events[eventName]) {
events[eventName].forEach(fn => {
fn(data);
});
}
};
return {
subscribe,
unsubscribe,
publish
};
})();
// Define the colleagues
const button1 = {
onClick: () => {
EventBus.publish('buttonClicked', { buttonId: 1 });
}
};
const button2 = {
onClick: () => {
EventBus.publish('buttonClicked', { buttonId: 2 });
}
};
const logger = {
log: data => {
console.log(`Button ${data.buttonId} clicked`);
}
};
// Subscribe the logger to the buttonClicked event
EventBus.subscribe('buttonClicked', logger.log);
// Trigger the onClick event for button1 and button2
button1.onClick();
button2.onClick();
In this example, the EventBus
object acts as the mediator, allowing the button1
and button2
objects to publish events. The logger
object subscribes to the buttonClicked
event and logs information about which button was clicked.
Implement the Mediator pattern using a centralized controller
Another way to implement the Mediator pattern is to use a centralized controller object that manages the communication between objects. Here's an example:
// Define the controller
const Controller = (() => {
const components = [];
const register = component => {
components.push(component);
};
const sendMessage = (sender, message) => {
components.forEach(component => {
if (component !== sender) {
component.receiveMessage(message);
}
});
};
return {
register,
sendMessage
};
})();
// Define the colleagues
class Component {
constructor(name) {
this.name = name;
Controller.register(this);
}
sendMessage(message) {
Controller.sendMessage(this, message);
}
receiveMessage(message) {
console.log(`${this.name} received message: ${message}`);
}
}
const component1 = new Component('Component 1');
const component2 = new Component('Component 2');
const component3 = new Component('Component 3');
// Send a message from component1 to all other components
component1.sendMessage('Hello, everyone!');
In this example, the Controller
object acts as the mediator, allowing the Component
objects to communicate with each other. Each Component
object registers itself with the Controller
, and can send and receive messages using the sendMessage
and receiveMessage
methods. When a message is sent, the Controller
forwards the message to all registered components except the sender.
Advantages and Disadvantages of the JavaScript Mediator Pattern
The JavaScript Mediator Pattern can provide several benefits, such as reduced coupling, improved code organization, easier testing, and improved performance. As much as it improves performance, it can introduce some drawbacks, such as increased complexity, increased memory usage, reduced flexibility, and potential performance overhead. By understanding the advantages and disadvantages of the pattern, developers can make informed decisions about when and how to use it effectively.
Summary
The Mediator Pattern is a behavioral design pattern that allows objects to communicate indirectly through a mediator object, promoting loose coupling and making the code more modular and maintainable. In JavaScript, the Mediator Pattern can be implemented using various techniques, including a mediator object that controls communication between objects or by using the Observer Pattern. By understanding the Mediator Pattern and how to implement it in JavaScript, developers can create better, more modular applications that are easier to maintain and extend.
References
Mediator pattern - Wikipedia
The Mediator Pattern - Learning JavaScript Design Patterns [Book] (oreilly.com)