Mediator Design Pattern


Here, we will see how to create Mediator Design Pattern with example.

Mediator Design Pattern

The Mediator design pattern centralizes communication between objects (colleagues) through a mediator. This prevents objects from communicating directly with one another, reducing dependencies and simplifying the system.

Example

An air traffic control system using the Mediator design pattern. The air traffic control tower centralizes communication between airplanes, coordinating take-offs and landings without the planes communicating directly with each other. We will explain in detail lator part of the article with code example.

Mediator Design Pattern

Advantages of the Mediator Pattern

  1. Decoupling of Objects - It reduces the direct dependencies between components, leading to a more maintainable and flexible system.
  2. Simplified Object Communication - Instead of objects communicating directly with one another (leading to complex interdependencies), all communication is managed through a central mediator.
  3. Easier Maintenance - Since communication logic is centralized, changes to interaction between components require only updating the mediator, instead of modifying multiple objects.
  4. Enhanced Code Reusability -  Objects can be reused more easily as they don’t depend on one another but rely on the mediator.
  5. Improved Readability -  The pattern makes communication flows between objects clearer, as all the interactions are managed in one place.
  6. Single Responsibility Principle -  Objects remain focused on their main duties, while the mediator handles interactions between them, adhering to the Single Responsibility Principle.

When to Use the Mediator Pattern

  1. Complex Communication Between Objects -  Use the mediator when there are many objects that need to communicate with each other, and the interdependencies make the system difficult to manage.
  2. Tightly Coupled Components -  If the system becomes hard to scale or maintain due to the number of direct dependencies between components, the mediator pattern can help by centralizing their communication.
  3. Recurrent Communication Patterns -  When the same kind of communication logic is repeated in multiple parts of the system, the mediator centralizes it, making it reusable and easier to update.
  4. Avoiding Spaghetti Code -  When complex inter-object communication leads to tangled, hard-to-follow code, the mediator can simplify these interactions.

Problems in a System Without a Mediator

  1. Tight Coupling -  Without the mediator pattern, components depend directly on each other, leading to tightly coupled code that’s difficult to modify or extend.
  2. Complex Communication Logic -  As more components interact, the number of communication paths increases exponentially, making the system complex and hard to maintain.
  3. Code Duplication -  Without a mediator, communication logic may need to be duplicated in multiple places, increasing the likelihood of errors and making future updates more difficult.
  4. Reduced Flexibility -  When objects are directly coupled, changing one often requires modifying others, reducing the system’s flexibility and increasing the cost of maintenance.

1. Real-World Example - Traffic Control System

A traffic control system is a real-world example of the mediator pattern. In an airport, for instance, an air traffic controller (mediator) coordinates the landings and take-offs of multiple airplanes (colleagues). Without the mediator, planes would have to communicate directly with each other to negotiate landing slots, leading to chaos. The air traffic controller centralizes the communication and directs planes as needed, ensuring that they don’t collide and that operations run smoothly.

Mediator Design Pattern

Image Explanation Prompt

The image should depict an airport traffic control system:

  • In the center, there is an air traffic control tower (the Mediator).
  • Around it, there are several airplanes (the Colleagues) that communicate through the tower rather than directly with each other.
  • Arrows from each airplane point to the tower to indicate communication, and the tower directs information back to the planes.

C# Code

using System;
using System.Collections.Generic;

// Mediator Interface
public interface ITrafficControlMediator
{
    void RegisterAirplane(Airplane airplane);
    void Notify(string message, Airplane airplane);
}

// Concrete Mediator
public class AirTrafficControl : ITrafficControlMediator
{
    private List<Airplane> _airplanes = new List<Airplane>();

    public void RegisterAirplane(Airplane airplane)
    {
        _airplanes.Add(airplane);
    }

    public void Notify(string message, Airplane airplane)
    {
        foreach (var otherAirplane in _airplanes)
        {
            if (otherAirplane != airplane)
            {
                otherAirplane.ReceiveMessage(message);
            }
        }
    }
}

// Colleague Class
public class Airplane
{
    private readonly ITrafficControlMediator _mediator;
    public string Name { get; }

    public Airplane(string name, ITrafficControlMediator mediator)
    {
        Name = name;
        _mediator = mediator;
        _mediator.RegisterAirplane(this);
    }

    public void SendRequest(string message)
    {
        Console.WriteLine($"{Name} sending message: {message}");
        _mediator.Notify($"{Name}: {message}", this);
    }

    public void ReceiveMessage(string message)
    {
        Console.WriteLine($"{Name} received message: {message}");
    }
}

// Example Usage
public class Program
{
    public static void Main(string[] args)
    {
        ITrafficControlMediator atc = new AirTrafficControl();

        Airplane airplane1 = new Airplane("Flight 101", atc);
        Airplane airplane2 = new Airplane("Flight 202", atc);
        Airplane airplane3 = new Airplane("Flight 303", atc);

        airplane1.SendRequest("Requesting landing permission");
        airplane2.SendRequest("Requesting takeoff clearance");

        // Output:
        // Flight 101 sending message: Requesting landing permission
        // Flight 202 received message: Flight 101: Requesting landing permission
        // Flight 303 received message: Flight 101: Requesting landing permission
        // Flight 202 sending message: Requesting takeoff clearance
        // Flight 101 received message: Flight 202: Requesting takeoff clearance
        // Flight 303 received message: Flight 202: Requesting takeoff clearance
    }
}
Mediator Design Pattern

2. Example - Chat Room

Imagine a chat room where multiple users can send and receive messages. Instead of having each user directly communicate with every other user, a mediator (chatroom) manages the communication.

Example in C#

using System;

public interface IChatRoomMediator
{
    void ShowMessage(User user, string message);
}

// Concrete Mediator
public class ChatRoom : IChatRoomMediator
{
    public void ShowMessage(User user, string message)
    {
        Console.WriteLine($"{DateTime.Now} [{user.Name}] : {message}");
    }
}

// Colleague Class
public class User
{
    private string _name;
    private IChatRoomMediator _chatMediator;

    public User(string name, IChatRoomMediator chatMediator)
    {
        _name = name;
        _chatMediator = chatMediator;
    }

    public string Name => _name;

    public void SendMessage(string message)
    {
        _chatMediator.ShowMessage(this, message);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var mediator = new ChatRoom();
        var user1 = new User("Rohatash", mediator);
        var user2 = new User("Mohit", mediator);

        user1.SendMessage("Hello, Bob!");
        user2.SendMessage("Hi Alice, how are you?");
    }
}

Here, the ChatRoom acts as a mediator between User objects. Each user communicates through the chat room, reducing the need for direct coupling between users.

Output

Mediator Design Pattern
Prev Next

Top Articles

  1. What is JSON
  2. How to convert a javaScript object in JSON object
  3. Some Important JSON Examples
  4. Common JSON Interview Question