Skip to content
SP StackPractices
intermediate

Mediator Pattern

Define an object that encapsulates how a set of objects interact. A behavioral design pattern for reducing chaotic dependencies.

Topics: design

Mediator Pattern

Overview

The Mediator Pattern is a behavioral design pattern that defines an object that encapsulates how a set of objects interact. Instead of objects referring to each other directly, they communicate through a central mediator. This reduces the number of direct connections between components and centralizes complex coordination logic.

When to Use

Use the Mediator Pattern when:

  • You have many objects that need to communicate in complex ways
  • The dependencies between objects create a tangled mess (spaghetti code)
  • You want to centralize complex coordination logic
  • Reusing an individual component is hard because it depends on many others
  • A change in one component forces changes in many others

Solution

Python

from abc import ABC, abstractmethod

class ChatMediator(ABC):
    @abstractmethod
    def send_message(self, message: str, sender):
        pass

    @abstractmethod
    def add_user(self, user):
        pass

class ChatRoom(ChatMediator):
    def __init__(self):
        self.users = []

    def add_user(self, user):
        self.users.append(user)

    def send_message(self, message: str, sender):
        for user in self.users:
            if user != sender:
                user.receive(message, sender.name)

class User:
    def __init__(self, name: str, mediator: ChatMediator):
        self.name = name
        self.mediator = mediator
        mediator.add_user(self)

    def send(self, message: str):
        print(f"{self.name} sends: {message}")
        self.mediator.send_message(message, self)

    def receive(self, message: str, from_name: str):
        print(f"{self.name} receives from {from_name}: {message}")

# Usage
room = ChatRoom()
alice = User("Alice", room)
bob = User("Bob", room)

alice.send("Hello everyone!")

JavaScript

class ChatRoom {
  constructor() {
    this.users = [];
  }

  addUser(user) {
    this.users.push(user);
  }

  sendMessage(message, sender) {
    for (const user of this.users) {
      if (user !== sender) {
        user.receive(message, sender.name);
      }
    }
  }
}

class User {
  constructor(name, mediator) {
    this.name = name;
    this.mediator = mediator;
    mediator.addUser(this);
  }

  send(message) {
    console.log(`${this.name} sends: ${message}`);
    this.mediator.sendMessage(message, this);
  }

  receive(message, fromName) {
    console.log(`${this.name} receives from ${fromName}: ${message}`);
  }
}

// Usage
const room = new ChatRoom();
const alice = new User("Alice", room);
const bob = new User("Bob", room);

alice.send("Hello everyone!");

Java

import java.util.ArrayList;
import java.util.List;

public interface ChatMediator {
    void sendMessage(String message, User sender);
    void addUser(User user);
}

public class ChatRoom implements ChatMediator {
    private final List<User> users = new ArrayList<>();

    public void addUser(User user) {
        users.add(user);
    }

    public void sendMessage(String message, User sender) {
        for (User user : users) {
            if (user != sender) {
                user.receive(message, sender.getName());
            }
        }
    }
}

public class User {
    private final String name;
    private final ChatMediator mediator;

    public User(String name, ChatMediator mediator) {
        this.name = name;
        this.mediator = mediator;
        mediator.addUser(this);
    }

    public String getName() { return name; }

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

    public void receive(String message, String fromName) {
        System.out.println(name + " receives from " + fromName + ": " + message);
    }
}

// Usage
ChatRoom room = new ChatRoom();
User alice = new User("Alice", room);
User bob = new User("Bob", room);
alice.send("Hello everyone!");

Explanation

The Mediator Pattern has two roles:

  • Mediator (ChatRoom): Defines the interface for communication between components
  • Colleagues (User): Objects that communicate through the mediator instead of directly

Without the mediator, each user would need a reference to every other user. With it, each user only needs a reference to the mediator.

Variants

VariantDescriptionUse Case
Event BusDecoupled pub/sub via a central channelLarge systems with many publishers/subscribers
Command BusCommands routed through a central handlerCQRS, task dispatching
Dialog DirectorUI widgets coordinated by a dialog controllerForm validation, wizard flows

Best Practices

  • Keep the mediator focused on coordination, not business logic
  • Avoid turning the mediator into a god object — if it grows too large, split it
  • Document which events the mediator handles so colleagues know what to expect
  • Consider an event bus for very large systems where a single mediator would become a bottleneck
  • Make the mediator observable so external systems can monitor interactions

Common Mistakes

  • Putting too much logic into the mediator, creating a “god class” that is hard to maintain
  • Using a mediator when simple direct method calls would suffice (over-engineering)
  • Making the mediator a bottleneck by centralizing all communication in a synchronous blocking fashion
  • Not documenting the mediator’s role, making it hard to understand why components don’t communicate directly
  • Allowing the mediator to leak colleague details to other colleagues

Frequently Asked Questions

Q: Is Mediator the same as Observer? A: Related but different. Observer is a one-to-many dependency where subjects notify observers. Mediator centralizes many-to-many communication. An event bus can serve as both.

Q: What is the difference between Mediator and Facade? A: Facade provides a simplified interface to a subsystem. Mediator coordinates communication between peer objects. Facade is about simplifying access; Mediator is about decoupling peers.