Exploring the Mediator Design Pattern

In the world of software design, maintaining a balance between simplicity and flexibility is a perpetual challenge. The Mediator Design Pattern stands out as a solution to address this balance, offering a way to facilitate communication between components without creating tight coupling among them. This article delves into the Mediator pattern, using a Python implementation as an illustrative example.

What?

The mediator design pattern is a behaviour design pattern that promotes loose coupling among multiple objects by centralising their communication through a mediator object.

Code

from abc import ABC, abstractmethod

# Mediator: Abstract class defining communication methods
class ATCMediator(ABC):
    @abstractmethod
    def register_flight(self, flight):
        pass

    @abstractmethod
    def send_message(self, message, sender_flight):
        pass

# ConcreteMediator: ATCTower
class ATCTower(ATCMediator):
    def __init__(self):
        self.flights = {}

    def register_flight(self, flight):
        self.flights[flight.flight_number] = flight

    def send_message(self, message, sender_flight):
        for flight_number, flight in self.flights.items():
            if flight_number != sender_flight.flight_number:
                flight.receive_message(message)

# Colleague: Abstract class representing flights
class Flight(ABC):
    def __init__(self, flight_number, mediator):
        self.flight_number = flight_number
        self.mediator = mediator

    def send_message(self, message):
        self.mediator.send_message(message, self)

    @abstractmethod
    def receive_message(self, message):
        pass

# ConcreteColleague: CommercialFlight
class CommercialFlight(Flight):
    def receive_message(self, message):
        print(f"Commercial flight {self.flight_number} received: {message}")

# ConcreteColleague: PrivateFlight
class PrivateFlight(Flight):
    def receive_message(self, message):
        print(f"Private flight {self.flight_number} received: {message}")

# Usage
if __name__ == "__main__":
    
    atc_mediator = ATCTower()

    flight1 = CommercialFlight("FL001", atc_mediator)
    flight2 = CommercialFlight("FL002", atc_mediator)
    flight3 = PrivateFlight("PF001", atc_mediator)

    atc_mediator.register_flight(flight1)
    atc_mediator.register_flight(flight2)
    atc_mediator.register_flight(flight3)

    flight1.send_message("Flight FL001 requesting landing clearance.")
    flight2.send_message("Flight FL002 requesting altitude change.")
    flight3.send_message("Flight PF001 requesting airport information.")

Output

Commercial flight FL002 received: Flight FL001 requesting landing clearance.
Private flight PF001 received: Flight FL001 requesting landing clearance.
Commercial flight FL001 received: Flight FL002 requesting altitude change.
Private flight PF001 received: Flight FL002 requesting altitude change.
Commercial flight FL001 received: Flight PF001 requesting airport information.
Commercial flight FL002 received: Flight PF001 requesting airport information.

Implementation

  • ATCMediator acts as mediator class

Use Case of the Mediator Design Pattern

  • Chat Application: In a chat application, users interact with each other through messages. Rather than having direct connections between individual users, a mediator could manage the communication. The mediator would receive messages from one user and relay them to the intended recipient, allowing for a more scalable and modular chat system.
  • Stock Trading System: In a stock trading system with multiple traders and market data sources, a mediator could facilitate communication between traders and market data feeds. Traders could send buy/sell orders through the mediator, which would then relay these orders to the appropriate market data sources and execute the trades. This promotes a flexible and extensible trading platform.
  • Smart Home Automation: In a smart home system where various devices (e.g., lights, thermostats, and security cameras) need to interact, a mediator could manage their communication. For example, a central home automation controller could act as the mediator, receiving commands from user interfaces or sensors and orchestrating the actions of different devices without them directly communicating with each other.
  • Air Traffic Control System (ATC): The provided example already aligns with a real-life scenario. In an air traffic control system, flights communicate through the ATC tower. The ATC tower acts as the mediator, managing the communication between different flights, providing instructions, and ensuring the safe and efficient flow of air traffic.
  • Online Marketplace: In an online marketplace where buyers and sellers interact, a mediator could handle communication between them. When a buyer places an order, the mediator could notify the seller to prepare the item for shipping. Similarly, the mediator could relay shipping and tracking information back to the buyer. This centralizes the communication flow and simplifies the interactions in a complex marketplace ecosystem.

    In these real-life examples, the Mediator pattern proves valuable in managing communication between disparate components, promoting modularity, and easing the maintenance and scalability of the systems. The pattern helps avoid a web of direct connections and dependencies, leading to more flexible and maintainable software architectures.

    Conclusion

    The mediator design pattern emerges as a powerful tool for addressing communication challenges in various real-life scenarios. By introducing a centralized mediator to manage interactions between disparate components, this pattern promotes a modular, scalable, and maintainable design. From facilitating communication in chat applications and smart home systems to orchestrating air traffic control and stock trading, the Mediator pattern proves its versatility. Its ability to reduce direct dependencies, centralize control, and promote a cleaner architecture makes it an invaluable asset in software development, particularly in scenarios where numerous entities need to communicate without becoming entangled in a complex web of connections. As software architects continue to seek elegant solutions for balancing simplicity and flexibility, the Mediator pattern remains a key player in fostering cohesive and adaptable systems.

    Resources

    For further exploration, make sure to check out these helpful resources:

    Leave a Comment