Mediator pattern defines an object (mediator) that encapsulates how a set of objects interact. It promotes loose coupling by preventing objects from referring to each other explicitly, allowing their interaction to be managed in one central place - the mediator. Instead of communicating directly, objects (colleagues) send messages to a mediator, which handles the routing of communication. This reduces the complexity and dependencies between objects.

Applicability

  • When objects communicate in a complex, tightly-coupled way that’s hard to manage and maintain
  • When you want to centralise control logic and reduce dependencies between communicating components
  • Especially useful in GUI systems, chat applications, air traffic control systems, or form handling, where multiple objects need to coordinate.

Pros and Cons

Advantages

  • Reduces coupling between components
    • Components (colleagues) do not need to know about each other; they only communicate with the mediator.
  • Centralised control logic
    • All communication logic is in one place, making it easier to manage, maintain, and extend.
  • Easier to modify and reuse components
    • Since components don’t depend on each other directly, they can be reused and replaced independently.

Drawbacks

  • Mediator can become a complex god object
    • If not designed carefully, the mediator can grow large and hard to manage, especially when it handles many interactions.
  • Overhead for simple communications
    • Introducing a mediator may be overkill if the interactions are minimal or simple.

Approach

  1. Define the Mediator interface that declares communication methods
  2. Define the Colleague abstract class or interface for components that will communicate via the mediator
  3. Implement concrete colleagues that use the mediator instead of communicating directly
  4. Implement the concrete mediator, handling the interactions and business logic between colleague objects

Components

  • Mediator (abstract/interface)
    • Declares methods to facilitate communication between colleague objects.
  • ConcreteMediator
    • Implements the coordination logic between colleague objects.
  • Colleague (abstract/interface)
    • A base component that holds a reference to the mediator and communicates through it.
  • ConcreteColleague
    • Implements component-specific behaviour and sends/receives messages via the mediator.

Example (Python)

# Concrete mediator
class SmartHomeMediator:
    def __init__(self):
        self.devices = {}
    
    def register_device(self, device_name, device):
        self.devices[device_name] = device
        device.mediator = self
    
    def notify(self, sender, event):
        if event == "motion_detected":
            # Turn on lights when motion is detected
            if "light" in self.devices:
                self.devices["light"].turn_on()
        
        elif event == "temperature_high":
            # Turn on AC when temperature is too high
            if "ac" in self.devices:
                self.devices["ac"].turn_on()
        
        elif event == "leaving_home":
            # Turn off all devices when leaving home
            for device in self.devices.values():
                if device != sender:
                    device.turn_off()
 
# Colleague
class SmartDevice:
    def __init__(self, name):
        self.name = name
        self.mediator = None
        self.is_on = False
    
    def turn_on(self):
        self.is_on = True
        print(f"{self.name} turned ON")
    
    def turn_off(self):
        self.is_on = False
        print(f"{self.name} turned OFF")
 
# Concrete collegue
class MotionSensor(SmartDevice):
    def detect_motion(self):
        print("Motion detected!")
        self.mediator.notify(self, "motion_detected")
 
 
class ThermostatSensor(SmartDevice):
    def set_temperature(self, temp):
        print(f"Temperature set to {temp}")
        if temp > 25:  # Celsius
            self.mediator.notify(self, "temperature_high")
 
 
class RemoteControl(SmartDevice):
    def leaving_home_button(self):
        print("Leaving home button pressed")
        self.mediator.notify(self, "leaving_home")
 
 
# Client
home = SmartHomeMediator()
 
light = SmartDevice("Living Room Light")
ac = SmartDevice("Air Conditioner")
motion_sensor = MotionSensor("Hallway Sensor")
thermostat = ThermostatSensor("Main Thermostat") 
remote = RemoteControl("Remote Control")
 
home.register_device("light", light)
home.register_device("ac", ac)
home.register_device("motion_sensor", motion_sensor)
home.register_device("thermostat", thermostat)
home.register_device("remote", remote)
 
# Test scenarios
motion_sensor.detect_motion()  # Should turn on lights
thermostat.set_temperature(28)  # Should turn on AC
remote.leaving_home_button()  # Should turn everything off

Back to parent page: Behavioural Patterns

Design_Pattern Behavioural_Design_Patterns Mediator_Pattern SOFT3202