Skip to main content

Mediator Pattern

Reduce coupling by centralizing complex communications

Pattern Overview

🤝 Mediator Pattern

The Mediator Pattern defines how objects interact with each other. Instead of objects communicating directly, they communicate through a central mediator, reducing coupling between components.

Core Concepts

🔹 Mediator Interface - Defines communication contract
🔹 Concrete Mediator - Implements interaction logic between colleagues
🔹 Colleague Classes - Components that communicate via mediator
🔹 Centralized Control - All interactions flow through mediator

Real-World Applications

Chat Systems - Users communicate through chat room mediator Air Traffic Control - Aircraft coordinate through ATC mediator UI Forms - Form components interact through form mediator Event Systems - Publishers and subscribers communicate via event bus

Communication Patterns

Before Mediator: Objects have direct references to each other (N×N complexity) After Mediator: Objects only know about mediator (N×1 complexity) Result: Reduced coupling and centralized interaction logic

Implementation Benefits

Loose coupling - Colleagues don't reference each other directly
Centralized control - Interaction logic in one place
Reusable components - Colleagues can be used in different contexts
Easy to extend - Add new interaction patterns in mediator

Examples:
Users communicate in chat room without direct references to each other
Input:
const { chatRoom, alice, bob, moderator } = createChatRoom();

alice.send('Hello everyone!');
bob.send('Hi Alice!');
moderator.muteUser('Bob');
alice.send('How is everyone doing?');

console.log(`Total users: ${chatRoom.getUserCount()}`);
Output:
Bob received from Alice: "Hello everyone!"
ModeratorMike (moderator) received from Alice: "Hello everyone!"
Alice received from Bob: "Hi Alice!"
ModeratorMike (moderator) received from Bob: "Hi Alice!"
ModeratorMike muted Bob
Alice received from Bob: "How is everyone doing?"
ModeratorMike (moderator) received from Alice: "How is everyone doing?"
Total users: 4
Aircraft coordinate landing and takeoff through central ATC system
Input:
const { atc, flight101, privatePlane } = createAirport();

console.log(flight101.requestLanding());
console.log(privatePlane.requestLanding());
console.log(flight101.requestTakeoff());
Output:
ATC to AA101: Cleared to land on Runway 1
ATC to N123AB: Cleared to land on Runway 2
ATC to AA101: Cleared for takeoff on Runway 1
Form components interact through mediator to enable/disable buttons based on input validation
Input:
const form = createAuthForm();
const { username, password, loginButton } = form.getComponents();

console.log(`Login enabled: ${loginButton.isEnabled()}`);
username.setValue('john');
console.log(`Login enabled: ${loginButton.isEnabled()}`);
password.setValue('secret');
console.log(`Login enabled: ${loginButton.isEnabled()}`);
Output:
Login enabled: false
Login enabled: false
Login enabled: true

Concepts

design patternssoftware architecturecode organizationobject-oriented programming

Complexity Analysis

Time:O(1)
Space:O(n)

Implementation

chat-system

Time: O(n) | Space: O(n)
// Mediator interface
interface ChatMediator {
  sendMessage(message: string, user: ChatUser): void;
  addUser(user: ChatUser): void;
  removeUser(user: ChatUser): void;
}

// Concrete mediator - Chat Room
class ChatRoom implements ChatMediator {
  private users: ChatUser[] = [];

  addUser(user: ChatUser): void {
    this.users.push(user);
    console.log(`${user.getName()} joined the chat`);
  }

  removeUser(user: ChatUser): void {
    const index = this.users.indexOf(user);
    if (index !== -1) {
      this.users.splice(index, 1);
      console.log(`${user.getName()} left the chat`);
    }
  }

  sendMessage(message: string, sender: ChatUser): void {
    this.users.forEach(user => {
      if (user !== sender) {
        user.receive(message, sender.getName());
      }
    });
  }

  getUserCount(): number {
    return this.users.length;
  }
}

// Colleague classes
abstract class ChatUser {
  constructor(
    protected name: string,
    protected mediator: ChatMediator
  ) {
    this.mediator.addUser(this);
  }

  abstract send(message: string): void;
  abstract receive(message: string, from: string): void;

  getName(): string {
    return this.name;
  }
}

class RegularUser extends ChatUser {
  send(message: string): void {
    console.log(`${this.name} sends: "${message}"`);
    this.mediator.sendMessage(message, this);
  }

  receive(message: string, from: string): void {
    console.log(`${this.name} received from ${from}: "${message}"`);
  }
}