Skip to content

Demystifying the Mediator Design Pattern

Posted on:September 24, 2022 at 01:13 PM

In this blog post, we’ll unravel the intricacies of the Mediator Design Pattern. This pattern plays a pivotal role in simplifying communication between multiple components within a system. As the number of components grows, managing communication can become a tangled web. The Mediator Design Pattern offers an elegant solution to this issue.

Table of contents

Open Table of contents

Sections

Understanding the Mediator Design Pattern

Imagine a software system with numerous components that need to communicate back and forth. In such a complex scenario, you might find that these components communicate with each other using various channels. This results in tight coupling, as each component must be aware of others in the system, leading to an impractical and chaotic design.

A classic example of such a scenario is a chat application. When dealing with a limited number of users, managing their interactions individually might seem manageable. However, as the user base grows, keeping track of every user becomes unfeasible. This is where the Mediator Design Pattern comes to the rescue.

MediatorGraphicProblem

The Mediator Design Pattern introduces a communication layer in the system. Each component only knows about the central mediator, which, in turn, maintains a list of all the components. This arrangement creates a centralized communication hub, offering several advantages:

Reduced Complexity:

Components no longer need to know about every other component; they communicate only through the mediator.

Standardized Communication:

The mediator enforces a uniform way for components to interact, simplifying the exchange of information.

Loose Coupling:

Components don’t directly communicate with each other; they communicate through the mediator, reducing dependencies. With this theoretical foundation in place, let’s delve into creating a simple chat system using the Mediator Design Pattern.

MediatorGraphicSolution

Implementing a Basic Chat System with a Mediator

For our example, we’ll create a rudimentary chat system with two main components: ChatUser and Mediator. These components need to be aware of each other, as ChatUser communicates through the Mediator.

Let’s start with the ChatUser class. This class holds a user’s name and a reference to the mediator:

ChatUser

public class ChatUser {
    String name;
    Mediator mediator;

    public ChatUser(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }

    public void sendMessage(String message) {
        System.out.println(name + " : sending message " + message);
        mediator.sendMessage(message, this);
    }

    public void receiveMessage(String message) {
        System.out.println(name + ": Received Message " +  message);
    }
}

In our example, we assume that this is a group chat, so the ChatUser class contains methods to send and receive messages. The send method sends a message to all other users, excluding the sender.

Next, we create the Mediator class, which maintains a list of chat users and facilitates message forwarding:

Mediator

public class Mediator {
    ArrayList<ChatUser> users = new ArrayList<>();

    public Mediator addUser(ChatUser user) {
        users.add(user);
        return this;
    }

    public void sendMessage(String message, ChatUser source){
        for (ChatUser user : users) {
            if (user != source) {
                user.receiveMessage(message);
            }
        }
    }
}

The Mediator class includes a method to add users to its list and another method to send messages. When a user sends a message, the mediator forwards it to all other users except the sender.

In our main application, we create a mediator and three chat users. The users are then added to the mediator’s list. One of the users, Carol, sends a group chat message:

Client

public class Client {
    public static void main(String[] args) {
        Mediator mediator = new Mediator();
        ChatUser eli = new ChatUser("Eli", mediator);
        ChatUser mogul = new ChatUser("Mogul", mediator);
        ChatUser soma = new ChatUser("Soma", mediator);

        mediator.addUser(eli).addUser(mogul).addUser(soma);

        soma.sendMessage("Hola ¬¬");

    }
}

When we run this program, Soma’s message is delivered to both Eli and Mogul, showcasing the Mediator Design Pattern in action.

Benefits of the Mediator Design Pattern

The Mediator Design Pattern brings several advantages to your software architecture:

Centralized Control:

It centralizes communication control, making it easier to manage interactions.

Reduced Complexity:

The pattern simplifies the relationships between components by enforcing a single communication channel.

Easier Maintenance:

As components interact through the mediator, changes or additions become less invasive, reducing maintenance overhead.

Conclusion

The Mediator Design Pattern is a powerful tool for streamlining communication in software systems with multiple components. By introducing a central mediator, you can reduce complexity, improve maintainability, and foster loose coupling between components.

This article has provided a clear understanding of the Mediator Design Pattern and demonstrated its application in a practical scenario. This pattern serves as an essential asset when designing systems that require organized and efficient communication between components.

Incorporating the Mediator Design Pattern in your projects can lead to cleaner and more scalable software architectures, allowing your applications to grow without becoming overly complex.

Thank you for reading, and we look forward to sharing more insights in the future! Happy coding! 🚀