Bird
Raised Fist0
LLDsystem_design~7 mins

Mediator pattern in LLD - System Design Guide

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Problem Statement
When multiple components communicate directly with each other, the system becomes tightly coupled and complex. Changes in one component can cause ripple effects, making maintenance and scaling difficult.
Solution
The Mediator pattern introduces a central object that handles communication between components. Instead of talking directly, components send messages to the mediator, which then routes them appropriately, reducing dependencies and simplifying interactions.
Architecture
Component A
Component B
Component C

This diagram shows multiple components communicating only through a central Mediator, which manages all interactions and routes messages.

Trade-offs
✓ Pros
Reduces direct dependencies between components, making the system easier to maintain.
Centralizes control of communication, simplifying debugging and modification.
Improves code reusability by decoupling components from each other.
✗ Cons
Mediator can become a complex, monolithic component if not designed carefully.
Introduces an extra layer of indirection, which may add slight performance overhead.
Overuse can lead to a single point of failure or bottleneck in communication.
Use when multiple components interact in complex ways and tight coupling makes maintenance or scaling difficult, especially in UI event handling or messaging systems.
Avoid when components have simple, direct interactions or when the number of components is very small, as the mediator adds unnecessary complexity.
Real World Examples
Airbnb
Uses Mediator pattern in their booking system to coordinate interactions between availability, pricing, and payment components without tight coupling.
Discord
Applies Mediator pattern to manage communication between different chat modules and notification systems, centralizing message routing.
LinkedIn
Uses Mediator pattern in their UI components to handle complex user interactions and event propagation cleanly.
Code Example
Before: ComponentA calls ComponentB directly, creating tight coupling. After: Both components communicate only through the Mediator, which routes events and reduces dependencies.
LLD
### Before applying Mediator pattern (tight coupling)

class ComponentA:
    def __init__(self, component_b):
        self.component_b = component_b

    def do_a(self):
        print("Component A does something")
        self.component_b.do_b()

class ComponentB:
    def do_b(self):
        print("Component B does something")

# Usage
b = ComponentB()
a = ComponentA(b)
a.do_a()


### After applying Mediator pattern (decoupled communication)

class Mediator:
    def __init__(self):
        self.component_a = ComponentA(self)
        self.component_b = ComponentB(self)

    def notify(self, sender, event):
        if sender == self.component_a and event == "A_done":
            self.component_b.do_b()

class ComponentA:
    def __init__(self, mediator):
        self.mediator = mediator

    def do_a(self):
        print("Component A does something")
        self.mediator.notify(self, "A_done")

class ComponentB:
    def __init__(self, mediator):
        self.mediator = mediator

    def do_b(self):
        print("Component B does something")

# Usage
mediator = Mediator()
mediator.component_a.do_a()
OutputSuccess
Alternatives
Observer pattern
Observer allows components to subscribe to events directly, while Mediator centralizes communication through one object.
Use when: Choose Observer when you want a one-to-many dependency without central control.
Event Bus
Event Bus is a more decoupled, publish-subscribe system without a central mediator controlling all interactions.
Use when: Choose Event Bus for highly decoupled systems with many independent event producers and consumers.
Summary
Mediator pattern centralizes communication between components to reduce tight coupling.
It simplifies maintenance by routing interactions through a single mediator object.
Overuse can cause the mediator to become complex and a potential bottleneck.

Practice

(1/5)
1. What is the main purpose of the Mediator pattern in system design?
easy
A. To store data persistently in a database
B. To increase direct communication between all components
C. To replace all components with a single monolithic class
D. To centralize communication between components and reduce dependencies

Solution

  1. Step 1: Understand the role of Mediator

    The Mediator pattern acts as a central hub to manage communication between components, avoiding direct links between them.
  2. Step 2: Compare options with Mediator's purpose

    To centralize communication between components and reduce dependencies correctly states the purpose: centralizing communication and reducing dependencies. Other options describe unrelated or incorrect behaviors.
  3. Final Answer:

    To centralize communication between components and reduce dependencies -> Option D
  4. Quick Check:

    Mediator centralizes communication = A [OK]
Hint: Mediator centralizes communication, not direct links [OK]
Common Mistakes:
  • Thinking Mediator increases direct component communication
  • Confusing Mediator with data storage patterns
  • Assuming Mediator merges components into one
2. Which of the following is the correct way to define a Mediator interface in a low-level design?
easy
A. interface Mediator { void notify(Component sender, String event); }
B. class Mediator { void notifyAll(); }
C. interface Mediator { void sendMessage(String message); }
D. class Mediator { void receive(Component sender); }

Solution

  1. Step 1: Identify typical Mediator method signature

    The Mediator usually has a method to notify it about events from components, often with sender and event details.
  2. Step 2: Match method signatures to this pattern

    interface Mediator { void notify(Component sender, String event); } matches this pattern with notify(Component sender, String event). Others lack sender info or use incorrect method names.
  3. Final Answer:

    interface Mediator { void notify(Component sender, String event); } -> Option A
  4. Quick Check:

    Notify method with sender and event = B [OK]
Hint: Mediator notify method includes sender and event [OK]
Common Mistakes:
  • Omitting sender parameter in notify method
  • Using generic sendMessage without context
  • Naming methods incorrectly for Mediator role
3. Given the following code snippet, what will be the output?
class Mediator {
  notify(sender, event) {
    if (event === 'A') return 'Handled A';
    if (event === 'B') return 'Handled B';
    return 'Unknown event';
  }
}

const mediator = new Mediator();
console.log(mediator.notify('Component1', 'B'));
medium
A. Handled A
B. Error: notify method missing
C. Handled B
D. Unknown event

Solution

  1. Step 1: Analyze notify method logic

    The method returns 'Handled A' if event is 'A', 'Handled B' if event is 'B', else 'Unknown event'.
  2. Step 2: Check the call with event 'B'

    The call is mediator.notify('Component1', 'B'), so it matches the second condition and returns 'Handled B'.
  3. Final Answer:

    Handled B -> Option C
  4. Quick Check:

    Event 'B' returns 'Handled B' [OK]
Hint: Match event string exactly in notify method [OK]
Common Mistakes:
  • Confusing event 'B' with 'A'
  • Assuming default case triggers for known events
  • Expecting error due to missing parameters
4. In the following Mediator implementation, what is the main issue?
class Mediator {
  notify(sender, event) {
    if (event === 'start') {
      sender.start();
    } else if (event === 'stop') {
      sender.stop();
    }
  }
}

class Component {
  start() { console.log('Started'); }
  stop() { console.log('Stopped'); }
}

const mediator = new Mediator();
const comp = new Component();
mediator.notify(comp, 'start');
medium
A. Component class lacks notify method
B. Mediator calls methods on sender directly, creating tight coupling
C. notify method does not handle unknown events
D. Missing constructor in Mediator class

Solution

  1. Step 1: Review Mediator's notify method behavior

    The Mediator calls start() or stop() directly on the sender component.
  2. Step 2: Identify design issue

    This direct call creates tight coupling between Mediator and Component, defeating the purpose of loose coupling in Mediator pattern.
  3. Final Answer:

    Mediator calls methods on sender directly, creating tight coupling -> Option B
  4. Quick Check:

    Tight coupling breaks Mediator pattern goal = A [OK]
Hint: Mediator should avoid calling sender methods directly [OK]
Common Mistakes:
  • Ignoring tight coupling caused by direct calls
  • Thinking missing notify in Component is an error
  • Assuming constructor absence causes failure
5. You are designing a chat application where multiple users send messages to each other. Which design using the Mediator pattern best fits this scenario?
hard
A. A ChatRoom mediator receives messages from users and forwards them to the intended recipients.
B. Users store messages locally and synchronize with a database periodically.
C. Each user sends messages directly to all other users without a central controller.
D. Users communicate only through email notifications handled by a separate service.

Solution

  1. Step 1: Understand the chat communication needs

    Users need a central place to send and receive messages without direct dependencies on each other.
  2. Step 2: Match with Mediator pattern usage

    A ChatRoom mediator receives messages from users and forwards them to the intended recipients. describes a ChatRoom mediator that manages message routing, fitting the Mediator pattern perfectly.
  3. Final Answer:

    A ChatRoom mediator receives messages from users and forwards them to the intended recipients. -> Option A
  4. Quick Check:

    Central message routing = C [OK]
Hint: Mediator centralizes message routing in chat apps [OK]
Common Mistakes:
  • Choosing direct user-to-user messaging (no mediator)
  • Confusing data storage with communication pattern
  • Selecting unrelated communication methods