Drani Academy – Interview Question, Search Job, Tuitorials, Cheat Sheet, Project, eBook

Design Patterns

Tutorials – Design Patterns

 
Chapter 21: Mediator Pattern

 

The Mediator Pattern is a behavioral design pattern that promotes loose coupling among objects by encapsulating how they interact and communicate. It centralizes the communication logic, allowing objects to communicate through a mediator rather than directly with each other. This pattern is often used to manage complex relationships and interactions between multiple objects in a system.

Understanding the Mediator Pattern

In software development, especially in large-scale applications, various objects often need to communicate and collaborate with each other. As the number of interactions between objects increases, managing these interactions becomes challenging. The Mediator Pattern addresses this challenge by introducing a mediator object that coordinates communication among objects without requiring them to have explicit knowledge of each other.

Key Participants:

  1. Mediator: The mediator is an interface or an abstract class that defines the methods for communication between objects. It typically includes methods for registering, deregistering, and sending messages to colleagues.
  2. Concrete Mediator: A concrete mediator implements the mediator interface and manages the communication and coordination of colleague objects. It keeps references to colleague objects and enforces the rules for communication between them.
  3. Colleague: Colleagues are objects that need to communicate with each other. They interact with the mediator to send and receive messages. Colleagues are often unaware of the existence of other colleagues.
  4. Concrete Colleague: Concrete colleagues are specific implementations of the colleague interface. They communicate through the mediator, which helps in achieving loose coupling between objects.

How It Works

The Mediator Pattern promotes a more organized and centralized approach to communication. Here’s how the pattern works:

  1. Colleagues register with the mediator during initialization, providing their references.
  2. When a colleague wants to communicate with another colleague, it sends a message to the mediator rather than directly to the target colleague.
  3. The mediator receives the message, identifies the target colleague, and forwards the message to that colleague.
  4. Colleagues receive messages from the mediator and can take actions accordingly.
  5. The mediator enforces the rules and logic for communication between colleagues, which helps in maintaining loose coupling.

Use Cases

The Mediator Pattern is used in various scenarios:

  1. Chat Applications: In chat applications, a mediator can manage communication between users without users having to directly reference each other.
  2. Air Traffic Control: Air traffic control systems use a mediator to manage and coordinate communication between aircraft.
  3. Event Handling: In graphical user interfaces, a mediator can be used to manage events and communication between user interface components.
  4. Game Development: In multiplayer games, a mediator can handle player interactions and game events.
  5. Components Integration: When integrating different components or modules in an application, a mediator can facilitate communication and data exchange.

Implementing the Mediator Pattern

Let’s walk through the implementation of the Mediator Pattern:

  1. Define Mediator Interface: Create a mediator interface with methods for colleague registration, deregistration, and message passing.
  2. Create Concrete Mediator: Implement a concrete mediator class that manages the communication logic between colleagues. It keeps references to registered colleagues.
  3. Define Colleague Interface: Create a colleague interface with methods for receiving and sending messages through the mediator.
  4. Create Concrete Colleagues: Implement concrete colleague classes that implement the colleague interface. Colleagues communicate through the mediator.
  5. Client Code: The client code initializes the mediator and colleagues, registers colleagues with the mediator, and uses the mediator to send messages between colleagues.

Benefits of the Mediator Pattern

The Mediator Pattern offers several benefits:

  1. Decoupling: It promotes loose coupling among objects, reducing dependencies between them.
  2. Centralized Control: It centralizes control over object interactions, making it easier to manage complex relationships.
  3. Simplified Communication: It simplifies communication and collaboration between objects by providing a single point of contact.
  4. Scalability: It makes it easier to add new colleagues without affecting existing ones.
  5. Flexibility: The mediator can implement custom logic for communication between colleagues, providing flexibility in the interactions.

Drawbacks of the Mediator Pattern

While the Mediator Pattern is beneficial, it also has some drawbacks:

  1. Complexity: Implementing a mediator and managing object interactions can introduce complexity.
  2. Performance Overhead: In some cases, using a mediator may introduce a performance overhead due to the additional method calls involved in communication.

Example: Implementing a Chat Application

Let’s look at a simple example of implementing a chat application using the Mediator Pattern in Python:

# Mediator Interface
class ChatMediator:
    def add_user(self, user):
        pass
    def send_message(self, message, user):
        pass
# Concrete Mediator
class ConcreteChatMediator(ChatMediator):
    def __init__(self):
        self.users = []
    def add_user(self, user):
        self.users.append(user)
    def send_message(self, message, user):
        for u in self.users:
            if u != user:
                u.receive(message)
# Colleague Interface
class User:
    def __init__(self, name, mediator):
        self.name = name
        self.mediator = mediator
    def send(self, message):
        self.mediator.send_message(message, self)
    def receive(self, message):
        print(f"{self.name} received: {message}")
# Create Mediator
mediator = ConcreteChatMediator()
# Create Users
alice = User("Alice", mediator)
bob = User("Bob", mediator)
charlie = User("Charlie", mediator)
mediator.add_user(alice)
mediator.add_user(bob)
mediator.add_user(charlie)
# Communication through Mediator
alice.send("Hello, everyone!")

In this example, the ConcreteChatMediator centralizes communication between users (User objects) in a chat application.

Conclusion

The Mediator Pattern is a valuable tool for managing complex object interactions and promoting loose coupling in software design. It simplifies the communication between objects by introducing a mediator that handles the interactions. This pattern is especially useful in scenarios where multiple objects need to collaborate without being tightly coupled. In the next chapter, we’ll explore the Chain of Responsibility Pattern, which focuses on passing requests along a chain of handlers.

Scroll to Top