Skip to content

What is the Mediator Pattern?

Behavioral

The Mediator pattern acts as a middleman between different modules of a program that need to communicate or exchange data, facilitating many-to-many relationships without direct connections.

Humanly Described

Think of Airbnb: it serves as an intermediary between customers and homeowners, coordinating details like dates, pricing, and more to provide a seamless service.

Implementation Overview

This behavioral pattern involves two modules on either side, with a middleware component coordinating their interactions.

Use Cases

  • Simplifies complex code
  • Enhances code manageability and maintainability
  • Improved modularity
  • Reduced dependencies
  • Centralized control

Point of Approach

This pattern is ideal when one side cannot fully trust the service provider or wants to avoid dealing with complex configurations. It can be combined with the Facade design pattern to offer a user-friendly interface, making the service easier to use and understand without deep knowledge of the underlying system.

Code Samples

Rust
rust
// Define the Mediator trait
pub trait Mediator {
    fn deliver_msg(&self, msg: String, target_user: usize);
    fn add_user(&mut self) -> ChatroomUser;
}

pub struct ChatroomMediator {
    chat_room: Vec<ChatroomUser>,
}

impl Mediator for ChatroomMediator {
    fn deliver_msg(&self, msg: String, target_user: usize) {
        if let Some(user) = self.chat_room.get(target_user) {
            user.receive(msg);
        } else {
            println!("User not found");
        }
    }

    fn add_user(&mut self) -> ChatroomUser {
        let user = ChatroomUser;
        self.chat_room.push(user.clone());
        user
    }
}

pub trait User {
    fn receive(&self, msg: String);
    fn send_message(&self, msg: String, mediator: &dyn Mediator, target_user: usize);
}

#[derive(Clone)]
pub struct ChatroomUser;

impl User for ChatroomUser {
    fn receive(&self, msg: String) {
        println!("Received: {}", msg);
    }

    fn send_message(&self, msg: String, mediator: &dyn Mediator, target_user: usize) {
        mediator.deliver_msg(msg, target_user);
    }
}

fn main() {
    // Creating the mediator
    let mut mediator = ChatroomMediator {
        chat_room: Vec::new(),
    };

    // Creating the users
    let user_1 = mediator.add_user();
    let user_2 = mediator.add_user();

    user_1.send_message("hello from 1 to 2".to_string(), &mediator, 1);
    user_2.send_message("hello from 2 to 1".to_string(), &mediator, 0);
}
TypeScript
typescript
interface Mediator {
    sendMessage(message: string, sender: User): void;
    addUser(user: User): void;
}

class ChatRoomMediator implements Mediator {
    private users: User[] = [];
    addUser(user: User): void { this.users.push(user); }
    sendMessage(message: string, sender: User): void {
        this.users.forEach(user => { if (user !== sender) user.receive(message); });
    }
}

class User {
    constructor(private name: string, private mediator: Mediator) {}
    send(message: string): void { console.log(`${this.name} sends: ${message}`); this.mediator.sendMessage(message, this); }
    receive(message: string): void { console.log(`${this.name} receives: ${message}`); }
}

const mediator = new ChatRoomMediator();
const user1 = new User("Alice", mediator);
const user2 = new User("Bob", mediator);
mediator.addUser(user1);
mediator.addUser(user2);
user1.send("Hello, Bob!");
user2.send("Hi, Alice!");