JavaScript Mediator Pattern [In-Depth Tutorial]


JavaScript

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)

 

Olorunfemi Akinlua

Olorunfemi Akinlua

He is boasting over five years of experience in JavaScript, specializing in technical content writing and UX design. With a keen focus on programming languages, he crafts compelling content and designs user-friendly interfaces to enhance digital experiences across various domains. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment