← Back to Home

Mediator Pattern

Defines an object that encapsulates how a set of objects interact.

What is it?

The Mediator pattern centralizes complex communications and control logic between objects in a system, promoting loose coupling.

Example

interface ChatMediator {
  sendMessage(message: string, sender: User): void;
  addUser(user: User): void;
}

abstract class User {
  constructor(protected name: string, protected mediator: ChatMediator) {}
  abstract receive(message: string): void;
  send(message: string) {
    this.mediator.sendMessage(message, this);
  }
}

class ChatRoom implements ChatMediator {
  private users: User[] = [];

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

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

class ChatUser extends User {
  receive(message: string) {
    console.log(`[Message to ${this.name}]: ${message}`);
  }

  getName() {
    return this.name;
  }
}

// Usage
const mediator = new ChatRoom();
const alice = new ChatUser('Alice', mediator);
const bob = new ChatUser('Bob', mediator);

mediator.addUser(alice);
mediator.addUser(bob);

alice.send('Hello Bob!');
bob.send('Hi Alice!');

Common Uses

  • Chat applications
  • Form or module coordination
  • Decoupling tightly connected systems

When to Use

  • Too many objects interacting directly
  • You want to simplify object communications

Caution

  • Mediator can become a complex God object
  • Should be kept focused to avoid tight coupling again