Skip to content

Mediator Pattern

Category: Behavioral Pattern

Overview

Define an object that encapsulates how a set of objects interact. This pattern promotes loose coupling by keeping objects from referring to each other explicitly and lets you vary their interaction independently by centralizing complex communications and control logic.

Usage Guidelines

Use when:

  • Many objects communicate in complex ways
  • Want to centralize communication logic
  • Objects shouldn't depend on each other directly
  • Want to reuse objects in different contexts

Avoid when:

  • Objects have simple, straightforward interactions
  • Mediator indirection is unacceptable for performance
  • Mediator becomes too complex (God object)
  • Direct communication is clearer and simpler

Implementation

from __future__ import annotations
from abc import ABC, abstractmethod

class Mediator(ABC):
    """Abstract mediator interface."""

    @abstractmethod
    def send_message(self, message: str, sender: Colleague) -> None:
        """Send a message through the mediator."""
        pass

class Colleague(ABC):
    """Abstract colleague that communicates through mediator."""

    def __init__(self, mediator: Mediator) -> None:
        """Initialize colleague with a mediator."""
        self.mediator = mediator

    @abstractmethod
    def receive(self, message: str) -> None:
        """Receive a message from the mediator."""
        pass

    @abstractmethod
    def send(self, message: str) -> None:
        """Send a message through the mediator."""
        pass

class ChatRoom(Mediator):
    """Concrete mediator implementing a chat room."""

    def __init__(self) -> None:
        """Initialize chat room."""
        self.users: list[User] = []

    def register_user(self, user: User) -> None:
        """Register a user in the chat room."""
        if user not in self.users:
            self.users.append(user)

    def send_message(self, message: str, sender: Colleague) -> None:
        """Send message to all users except sender."""
        for user in self.users:
            if user != sender:
                user.receive(message)

class User(Colleague):
    """Concrete colleague representing a chat user."""

    def __init__(self, name: str, chatroom: ChatRoom) -> None:
        """Initialize user."""
        super().__init__(chatroom)
        self.name = name
        self.messages: list[str] = []
        chatroom.register_user(self)

    def receive(self, message: str) -> None:
        """Receive a message."""
        self.messages.append(f"Received: {message}")

    def send(self, message: str) -> None:
        """Send a message."""
        self.messages.append(f"Sent: {message}")
        self.mediator.send_message(message, self)

    def get_messages(self) -> list[str]:
        """Get all messages for this user."""
        return self.messages

Usage

# Chat room
chatroom = ChatRoom()
alice = User("Alice", chatroom)
bob = User("Bob", chatroom)
charlie = User("Charlie", chatroom)

alice.send("Hello everyone!")
# Bob and Charlie receive the message

bob.send("Hi Alice!")
# Alice and Charlie receive the message

print(alice.get_messages())
print(bob.get_messages())

Trade-offs

Benefits:

  1. Loose coupling with colleagues not referencing each other directly
  2. Centralized control of communication logic in one place
  3. Simplified objects as mediator handles complexity
  4. Colleagues can be reused with different mediators

Drawbacks:

  1. Mediator can become too complex and hard to maintain (God object)
  2. Single point of failure as mediator failure affects all colleagues
  3. Indirect communication can make debugging harder
  4. Mediator adds indirection overhead for performance

Real-World Examples

  • GUI frameworks with dialog boxes coordinating widgets
  • Chat applications with chat rooms mediating communications
  • Air traffic control coordinating aircraft
  • MVC controllers coordinating models and views
  • Observer
  • Facade
  • Command

API Reference

design_patterns.behavioral.mediator

Mediator Pattern Module

The Mediator pattern defines an object that encapsulates how a set of objects interact. It promotes loose coupling by keeping objects from referring to each other explicitly and lets you vary their interaction independently. The mediator centralizes complex communications and control logic between related objects.

Example

Chat room where users communicate through mediator:

chatroom = ChatRoom()
alice = User("Alice", chatroom)
bob = User("Bob", chatroom)

alice.send("Hi Bob!")  # Message sent through chatroom mediator
bob.send("Hello Alice!")

AirTrafficControl

Bases: Mediator

Mediator for coordinating aircraft.

Source code in src/design_patterns/behavioral/mediator.py
class AirTrafficControl(Mediator):
    """Mediator for coordinating aircraft."""

    def __init__(self) -> None:
        """Initialize air traffic control."""
        self.aircraft: list[Aircraft] = []

    def register_aircraft(self, aircraft: Aircraft) -> None:
        """Register an aircraft.

        Args:
            aircraft: Aircraft to register.
        """
        if aircraft not in self.aircraft:
            self.aircraft.append(aircraft)

    def send_message(self, message: str, sender: Colleague) -> None:
        """Broadcast message to all aircraft.

        Args:
            message: Message to broadcast.
            sender: Aircraft sending the message.
        """
        for aircraft in self.aircraft:
            if aircraft != sender:
                aircraft.receive(message)

    def request_landing(self, aircraft: Aircraft) -> str:
        """Handle landing request.

        Args:
            aircraft: Aircraft requesting landing.

        Returns:
            Landing permission status.
        """
        if isinstance(aircraft, Aircraft):
            return f"Landing clearance granted for {aircraft.call_sign}"
        return "Permission denied"

__init__()

Initialize air traffic control.

Source code in src/design_patterns/behavioral/mediator.py
def __init__(self) -> None:
    """Initialize air traffic control."""
    self.aircraft: list[Aircraft] = []

register_aircraft(aircraft)

Register an aircraft.

Parameters:

Name Type Description Default
aircraft Aircraft

Aircraft to register.

required
Source code in src/design_patterns/behavioral/mediator.py
def register_aircraft(self, aircraft: Aircraft) -> None:
    """Register an aircraft.

    Args:
        aircraft: Aircraft to register.
    """
    if aircraft not in self.aircraft:
        self.aircraft.append(aircraft)

request_landing(aircraft)

Handle landing request.

Parameters:

Name Type Description Default
aircraft Aircraft

Aircraft requesting landing.

required

Returns:

Type Description
str

Landing permission status.

Source code in src/design_patterns/behavioral/mediator.py
def request_landing(self, aircraft: Aircraft) -> str:
    """Handle landing request.

    Args:
        aircraft: Aircraft requesting landing.

    Returns:
        Landing permission status.
    """
    if isinstance(aircraft, Aircraft):
        return f"Landing clearance granted for {aircraft.call_sign}"
    return "Permission denied"

send_message(message, sender)

Broadcast message to all aircraft.

Parameters:

Name Type Description Default
message str

Message to broadcast.

required
sender Colleague

Aircraft sending the message.

required
Source code in src/design_patterns/behavioral/mediator.py
def send_message(self, message: str, sender: Colleague) -> None:
    """Broadcast message to all aircraft.

    Args:
        message: Message to broadcast.
        sender: Aircraft sending the message.
    """
    for aircraft in self.aircraft:
        if aircraft != sender:
            aircraft.receive(message)

Aircraft

Bases: Colleague

Concrete colleague representing an aircraft.

Source code in src/design_patterns/behavioral/mediator.py
class Aircraft(Colleague):
    """Concrete colleague representing an aircraft."""

    def __init__(self, call_sign: str, atc: AirTrafficControl) -> None:
        """Initialize aircraft.

        Args:
            call_sign: Aircraft call sign.
            atc: Air traffic control mediator.
        """
        super().__init__(atc)
        self.call_sign = call_sign
        self.messages: list[str] = []
        atc.register_aircraft(self)

    def receive(self, message: str) -> None:
        """Receive a message from ATC.

        Args:
            message: Message received.
        """
        self.messages.append(f"[{self.call_sign}] Received: {message}")

    def send(self, message: str) -> None:
        """Send a message to ATC.

        Args:
            message: Message to send.
        """
        self.messages.append(f"[{self.call_sign}] Sent: {message}")
        self.mediator.send_message(f"{self.call_sign}: {message}", self)

    def request_landing(self) -> str:
        """Request landing permission.

        Returns:
            Landing permission response.
        """
        if isinstance(self.mediator, AirTrafficControl):
            return self.mediator.request_landing(self)
        return "No ATC available"

__init__(call_sign, atc)

Initialize aircraft.

Parameters:

Name Type Description Default
call_sign str

Aircraft call sign.

required
atc AirTrafficControl

Air traffic control mediator.

required
Source code in src/design_patterns/behavioral/mediator.py
def __init__(self, call_sign: str, atc: AirTrafficControl) -> None:
    """Initialize aircraft.

    Args:
        call_sign: Aircraft call sign.
        atc: Air traffic control mediator.
    """
    super().__init__(atc)
    self.call_sign = call_sign
    self.messages: list[str] = []
    atc.register_aircraft(self)

receive(message)

Receive a message from ATC.

Parameters:

Name Type Description Default
message str

Message received.

required
Source code in src/design_patterns/behavioral/mediator.py
def receive(self, message: str) -> None:
    """Receive a message from ATC.

    Args:
        message: Message received.
    """
    self.messages.append(f"[{self.call_sign}] Received: {message}")

request_landing()

Request landing permission.

Returns:

Type Description
str

Landing permission response.

Source code in src/design_patterns/behavioral/mediator.py
def request_landing(self) -> str:
    """Request landing permission.

    Returns:
        Landing permission response.
    """
    if isinstance(self.mediator, AirTrafficControl):
        return self.mediator.request_landing(self)
    return "No ATC available"

send(message)

Send a message to ATC.

Parameters:

Name Type Description Default
message str

Message to send.

required
Source code in src/design_patterns/behavioral/mediator.py
def send(self, message: str) -> None:
    """Send a message to ATC.

    Args:
        message: Message to send.
    """
    self.messages.append(f"[{self.call_sign}] Sent: {message}")
    self.mediator.send_message(f"{self.call_sign}: {message}", self)

ChatRoom

Bases: Mediator

Concrete mediator implementing a chat room.

Source code in src/design_patterns/behavioral/mediator.py
class ChatRoom(Mediator):
    """Concrete mediator implementing a chat room."""

    def __init__(self) -> None:
        """Initialize chat room."""
        self.users: list[User] = []

    def register_user(self, user: User) -> None:
        """Register a user in the chat room.

        Args:
            user: User to register.
        """
        if user not in self.users:
            self.users.append(user)

    def send_message(self, message: str, sender: Colleague) -> None:
        """Send message to all users except sender.

        Args:
            message: Message to send.
            sender: User sending the message.
        """
        for user in self.users:
            if user != sender:
                user.receive(message)

__init__()

Initialize chat room.

Source code in src/design_patterns/behavioral/mediator.py
def __init__(self) -> None:
    """Initialize chat room."""
    self.users: list[User] = []

register_user(user)

Register a user in the chat room.

Parameters:

Name Type Description Default
user User

User to register.

required
Source code in src/design_patterns/behavioral/mediator.py
def register_user(self, user: User) -> None:
    """Register a user in the chat room.

    Args:
        user: User to register.
    """
    if user not in self.users:
        self.users.append(user)

send_message(message, sender)

Send message to all users except sender.

Parameters:

Name Type Description Default
message str

Message to send.

required
sender Colleague

User sending the message.

required
Source code in src/design_patterns/behavioral/mediator.py
def send_message(self, message: str, sender: Colleague) -> None:
    """Send message to all users except sender.

    Args:
        message: Message to send.
        sender: User sending the message.
    """
    for user in self.users:
        if user != sender:
            user.receive(message)

Colleague

Bases: ABC

Abstract colleague that communicates through mediator.

Source code in src/design_patterns/behavioral/mediator.py
class Colleague(ABC):
    """Abstract colleague that communicates through mediator."""

    def __init__(self, mediator: Mediator) -> None:
        """Initialize colleague with a mediator.

        Args:
            mediator: The mediator to use for communication.
        """
        self.mediator = mediator

    @abstractmethod
    def receive(self, message: str) -> None:
        """Receive a message from the mediator.

        Args:
            message: Message received.
        """
        pass

    @abstractmethod
    def send(self, message: str) -> None:
        """Send a message through the mediator.

        Args:
            message: Message to send.
        """
        pass

__init__(mediator)

Initialize colleague with a mediator.

Parameters:

Name Type Description Default
mediator Mediator

The mediator to use for communication.

required
Source code in src/design_patterns/behavioral/mediator.py
def __init__(self, mediator: Mediator) -> None:
    """Initialize colleague with a mediator.

    Args:
        mediator: The mediator to use for communication.
    """
    self.mediator = mediator

receive(message) abstractmethod

Receive a message from the mediator.

Parameters:

Name Type Description Default
message str

Message received.

required
Source code in src/design_patterns/behavioral/mediator.py
@abstractmethod
def receive(self, message: str) -> None:
    """Receive a message from the mediator.

    Args:
        message: Message received.
    """
    pass

send(message) abstractmethod

Send a message through the mediator.

Parameters:

Name Type Description Default
message str

Message to send.

required
Source code in src/design_patterns/behavioral/mediator.py
@abstractmethod
def send(self, message: str) -> None:
    """Send a message through the mediator.

    Args:
        message: Message to send.
    """
    pass

Mediator

Bases: ABC

Abstract mediator interface.

Source code in src/design_patterns/behavioral/mediator.py
class Mediator(ABC):
    """Abstract mediator interface."""

    @abstractmethod
    def send_message(self, message: str, sender: Colleague) -> None:
        """Send a message through the mediator.

        Args:
            message: Message to send.
            sender: Colleague sending the message.
        """
        pass

send_message(message, sender) abstractmethod

Send a message through the mediator.

Parameters:

Name Type Description Default
message str

Message to send.

required
sender Colleague

Colleague sending the message.

required
Source code in src/design_patterns/behavioral/mediator.py
@abstractmethod
def send_message(self, message: str, sender: Colleague) -> None:
    """Send a message through the mediator.

    Args:
        message: Message to send.
        sender: Colleague sending the message.
    """
    pass

SmartDevice

Bases: Colleague

Concrete colleague representing a smart home device.

Source code in src/design_patterns/behavioral/mediator.py
class SmartDevice(Colleague):
    """Concrete colleague representing a smart home device."""

    def __init__(self, name: str, smart_home: SmartHome) -> None:
        """Initialize smart device.

        Args:
            name: Device name.
            smart_home: Smart home mediator.
        """
        super().__init__(smart_home)
        self.name = name
        self.state: str = "off"
        self.notifications: list[str] = []
        smart_home.register_device(self)

    def receive(self, message: str) -> None:
        """Receive command from smart home.

        Args:
            message: Command received.
        """
        self.notifications.append(f"Command: {message}")

        if "turn on" in message.lower() or "activate" in message.lower():
            self.state = "on"
        elif "turn off" in message.lower() or "deactivate" in message.lower():
            self.state = "off"

    def send(self, message: str) -> None:
        """Send event to smart home.

        Args:
            message: Event message.
        """
        self.mediator.send_message(f"{self.name}: {message}", self)

    def trigger_event(self, event: str) -> None:
        """Trigger an event.

        Args:
            event: Event description.
        """
        self.send(event)

__init__(name, smart_home)

Initialize smart device.

Parameters:

Name Type Description Default
name str

Device name.

required
smart_home SmartHome

Smart home mediator.

required
Source code in src/design_patterns/behavioral/mediator.py
def __init__(self, name: str, smart_home: SmartHome) -> None:
    """Initialize smart device.

    Args:
        name: Device name.
        smart_home: Smart home mediator.
    """
    super().__init__(smart_home)
    self.name = name
    self.state: str = "off"
    self.notifications: list[str] = []
    smart_home.register_device(self)

receive(message)

Receive command from smart home.

Parameters:

Name Type Description Default
message str

Command received.

required
Source code in src/design_patterns/behavioral/mediator.py
def receive(self, message: str) -> None:
    """Receive command from smart home.

    Args:
        message: Command received.
    """
    self.notifications.append(f"Command: {message}")

    if "turn on" in message.lower() or "activate" in message.lower():
        self.state = "on"
    elif "turn off" in message.lower() or "deactivate" in message.lower():
        self.state = "off"

send(message)

Send event to smart home.

Parameters:

Name Type Description Default
message str

Event message.

required
Source code in src/design_patterns/behavioral/mediator.py
def send(self, message: str) -> None:
    """Send event to smart home.

    Args:
        message: Event message.
    """
    self.mediator.send_message(f"{self.name}: {message}", self)

trigger_event(event)

Trigger an event.

Parameters:

Name Type Description Default
event str

Event description.

required
Source code in src/design_patterns/behavioral/mediator.py
def trigger_event(self, event: str) -> None:
    """Trigger an event.

    Args:
        event: Event description.
    """
    self.send(event)

SmartHome

Bases: Mediator

Mediator for smart home devices.

Source code in src/design_patterns/behavioral/mediator.py
class SmartHome(Mediator):
    """Mediator for smart home devices."""

    def __init__(self) -> None:
        """Initialize smart home system."""
        self.devices: dict[str, SmartDevice] = {}
        self.events: list[str] = []

    def register_device(self, device: SmartDevice) -> None:
        """Register a smart device.

        Args:
            device: Device to register.
        """
        self.devices[device.name] = device

    def send_message(self, message: str, sender: Colleague) -> None:
        """Process device event.

        Args:
            message: Event message.
            sender: Device sending the event.
        """
        self.events.append(message)

        # Smart home logic based on events
        if "motion detected" in message.lower():
            # Turn on lights when motion detected
            if "lights" in self.devices:
                self.devices["lights"].receive("turn on")

        if "door opened" in message.lower():
            # Activate alarm when door opened
            if "alarm" in self.devices:
                self.devices["alarm"].receive("activate")

__init__()

Initialize smart home system.

Source code in src/design_patterns/behavioral/mediator.py
def __init__(self) -> None:
    """Initialize smart home system."""
    self.devices: dict[str, SmartDevice] = {}
    self.events: list[str] = []

register_device(device)

Register a smart device.

Parameters:

Name Type Description Default
device SmartDevice

Device to register.

required
Source code in src/design_patterns/behavioral/mediator.py
def register_device(self, device: SmartDevice) -> None:
    """Register a smart device.

    Args:
        device: Device to register.
    """
    self.devices[device.name] = device

send_message(message, sender)

Process device event.

Parameters:

Name Type Description Default
message str

Event message.

required
sender Colleague

Device sending the event.

required
Source code in src/design_patterns/behavioral/mediator.py
def send_message(self, message: str, sender: Colleague) -> None:
    """Process device event.

    Args:
        message: Event message.
        sender: Device sending the event.
    """
    self.events.append(message)

    # Smart home logic based on events
    if "motion detected" in message.lower():
        # Turn on lights when motion detected
        if "lights" in self.devices:
            self.devices["lights"].receive("turn on")

    if "door opened" in message.lower():
        # Activate alarm when door opened
        if "alarm" in self.devices:
            self.devices["alarm"].receive("activate")

User

Bases: Colleague

Concrete colleague representing a chat user.

Source code in src/design_patterns/behavioral/mediator.py
class User(Colleague):
    """Concrete colleague representing a chat user."""

    def __init__(self, name: str, chatroom: ChatRoom) -> None:
        """Initialize user.

        Args:
            name: User name.
            chatroom: Chat room mediator.
        """
        super().__init__(chatroom)
        self.name = name
        self.messages: list[str] = []
        chatroom.register_user(self)

    def receive(self, message: str) -> None:
        """Receive a message.

        Args:
            message: Message received.
        """
        self.messages.append(f"Received: {message}")

    def send(self, message: str) -> None:
        """Send a message.

        Args:
            message: Message to send.
        """
        self.messages.append(f"Sent: {message}")
        self.mediator.send_message(message, self)

    def get_messages(self) -> list[str]:
        """Get all messages for this user.

        Returns:
            List of messages.
        """
        return self.messages

__init__(name, chatroom)

Initialize user.

Parameters:

Name Type Description Default
name str

User name.

required
chatroom ChatRoom

Chat room mediator.

required
Source code in src/design_patterns/behavioral/mediator.py
def __init__(self, name: str, chatroom: ChatRoom) -> None:
    """Initialize user.

    Args:
        name: User name.
        chatroom: Chat room mediator.
    """
    super().__init__(chatroom)
    self.name = name
    self.messages: list[str] = []
    chatroom.register_user(self)

get_messages()

Get all messages for this user.

Returns:

Type Description
list[str]

List of messages.

Source code in src/design_patterns/behavioral/mediator.py
def get_messages(self) -> list[str]:
    """Get all messages for this user.

    Returns:
        List of messages.
    """
    return self.messages

receive(message)

Receive a message.

Parameters:

Name Type Description Default
message str

Message received.

required
Source code in src/design_patterns/behavioral/mediator.py
def receive(self, message: str) -> None:
    """Receive a message.

    Args:
        message: Message received.
    """
    self.messages.append(f"Received: {message}")

send(message)

Send a message.

Parameters:

Name Type Description Default
message str

Message to send.

required
Source code in src/design_patterns/behavioral/mediator.py
def send(self, message: str) -> None:
    """Send a message.

    Args:
        message: Message to send.
    """
    self.messages.append(f"Sent: {message}")
    self.mediator.send_message(message, self)