Bird
0
0
LLDsystem_design~15 mins

Mediator pattern in LLD - Deep Dive

Choose your learning style9 modes available
Overview - Mediator pattern
What is it?
The Mediator pattern is a design approach that helps different parts of a system communicate through a central point instead of talking directly to each other. It organizes interactions by having a mediator object that controls how components work together. This reduces complex dependencies and makes the system easier to manage and change.
Why it matters
Without the Mediator pattern, components in a system often depend heavily on each other, creating a tangled web of connections that is hard to understand and maintain. This can lead to bugs and slow down development. Using a mediator simplifies communication, making the system more flexible and easier to update or extend.
Where it fits
Before learning the Mediator pattern, you should understand basic object-oriented design principles like encapsulation and coupling. After this, you can explore other behavioral design patterns like Observer or Command, which also manage interactions but in different ways.
Mental Model
Core Idea
The Mediator pattern centralizes communication between components to reduce direct dependencies and simplify interaction.
Think of it like...
Imagine a busy airport control tower that coordinates all the planes landing and taking off. Instead of planes talking directly to each other and risking confusion, they communicate only with the control tower, which manages the timing and order safely and efficiently.
┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│ Component A │─────▶│             │◀─────│ Component B │
└─────────────┘      │  Mediator   │      └─────────────┘
                     │             │
┌─────────────┐      │             │      ┌─────────────┐
│ Component C │─────▶│             │◀─────│ Component D │
└─────────────┘      └─────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding component communication
🤔
Concept: Components in a system often need to interact to perform tasks together.
In many systems, different parts (components) need to send messages or data to each other. For example, a chat app has a user interface and a message handler that must work together. Usually, these components talk directly to each other.
Result
Components are connected but can become tightly linked, making changes difficult.
Understanding that direct communication creates dependencies helps see why managing interactions is important.
2
FoundationProblems with direct component links
🤔
Concept: Direct connections between many components create complex, hard-to-maintain systems.
When each component talks to many others, the system forms a tangled network. Changing one component might require changes in many others, increasing bugs and slowing development.
Result
The system becomes fragile and hard to update.
Recognizing the drawbacks of direct links motivates the need for a better communication method.
3
IntermediateIntroducing the Mediator role
🤔Before reading on: do you think having a central controller will increase or decrease system complexity? Commit to your answer.
Concept: A mediator acts as a central hub to manage all communication between components.
Instead of components talking directly, they send messages to the mediator. The mediator decides who should get the message and when. This reduces the number of direct connections.
Result
Components only know the mediator, simplifying their relationships.
Understanding that centralizing communication reduces dependencies clarifies how the mediator improves system design.
4
IntermediateMediator managing component interactions
🤔Before reading on: do you think the mediator should know all components or just some? Commit to your answer.
Concept: The mediator keeps references to all components and controls their interactions.
The mediator holds a list of components and their states. When one component sends a message, the mediator processes it and forwards it to the right components, possibly applying rules or logic.
Result
Communication is controlled and predictable, reducing unexpected side effects.
Knowing the mediator controls interactions helps prevent chaotic or unintended component behavior.
5
IntermediateDecoupling components with mediator
🤔
Concept: Components become independent and unaware of each other's details.
Since components only communicate with the mediator, they don't need to know about other components' existence or implementation. This allows changing or replacing components without affecting others.
Result
The system becomes more modular and easier to maintain.
Understanding decoupling through the mediator reveals how to build flexible systems.
6
AdvancedMediator pattern in large-scale systems
🤔Before reading on: do you think a single mediator can handle thousands of components efficiently? Commit to your answer.
Concept: In large systems, mediators can be designed hierarchically or specialized to handle scale.
For many components, a single mediator might become a bottleneck. To solve this, systems use multiple mediators organized in layers or domains, each managing a subset of components and communicating with other mediators.
Result
The system scales while keeping communication organized.
Knowing mediator patterns can be layered helps design scalable, maintainable systems.
7
ExpertHidden risks and mediator anti-patterns
🤔Before reading on: can a mediator become a source of complexity itself? Commit to your answer.
Concept: If a mediator grows too complex, it can become a bottleneck and hard to maintain, known as the 'God object' anti-pattern.
When mediators handle too many responsibilities or logic, they become large and difficult to understand. This defeats the purpose of simplifying communication. Experts split mediator logic or combine with other patterns to avoid this.
Result
Proper mediator design balances central control with manageable complexity.
Understanding mediator limits prevents creating new problems while solving old ones.
Under the Hood
The mediator holds references to all participating components and acts as a message router. When a component sends a request or event, it calls the mediator's method. The mediator then decides which components should receive the message and invokes their methods accordingly. This centralizes control flow and reduces direct component-to-component calls.
Why designed this way?
The pattern was created to reduce tight coupling between components, which makes systems fragile and hard to change. By introducing a mediator, the design enforces a single point of communication, simplifying dependencies and improving maintainability. Alternatives like direct communication or event broadcasting were less controlled and led to complex, error-prone systems.
┌─────────────┐       ┌─────────────┐       ┌─────────────┐
│ Component A │──────▶│             │──────▶│ Component B │
│ Component C │──────▶│  Mediator   │──────▶│ Component D │
└─────────────┘       └─────────────┘       └─────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does the mediator eliminate all dependencies between components? Commit yes or no.
Common Belief:The mediator removes all dependencies, so components are completely independent.
Tap to reveal reality
Reality:Components still depend on the mediator interface, so there is a dependency, just centralized.
Why it matters:Ignoring this can lead to overloading the mediator and creating a single point of failure.
Quick: Is the mediator always a simple, lightweight object? Commit yes or no.
Common Belief:The mediator is always simple and easy to maintain.
Tap to reveal reality
Reality:In complex systems, mediators can become large and complicated, turning into 'God objects'.
Why it matters:This can make the system harder to maintain and understand, defeating the pattern's purpose.
Quick: Does using a mediator mean components never communicate directly? Commit yes or no.
Common Belief:Components never communicate directly once a mediator is used.
Tap to reveal reality
Reality:Sometimes components still communicate directly for performance or simplicity, but this should be minimized.
Why it matters:Assuming no direct communication can lead to unnecessary complexity or performance issues.
Quick: Can a mediator pattern solve all communication problems in a system? Commit yes or no.
Common Belief:The mediator pattern is a universal solution for all component communication issues.
Tap to reveal reality
Reality:It is one tool among many; sometimes other patterns like Observer or Event Bus are better suited.
Why it matters:Misusing the mediator can lead to poor design choices and system inefficiencies.
Expert Zone
1
A well-designed mediator balances control and simplicity, avoiding becoming a monolithic 'God object'.
2
Mediator implementations often combine with event-driven or observer patterns to handle asynchronous communication.
3
In distributed systems, mediators can be implemented as message brokers or service buses, extending the pattern beyond in-memory objects.
When NOT to use
Avoid the mediator pattern when component interactions are simple or when performance is critical and direct communication is more efficient. Alternatives include Observer pattern for event notification or direct method calls for tightly coupled components.
Production Patterns
In real systems, mediators appear as controllers in MVC architectures, message brokers in microservices, or event buses in UI frameworks. They often handle validation, routing, and coordination logic centrally to keep components focused on their core tasks.
Connections
Observer pattern
Both manage communication but Observer uses broadcast to multiple listeners, while Mediator centralizes control.
Understanding Mediator clarifies when to centralize communication versus when to broadcast events.
Air traffic control
Mediator pattern mirrors how air traffic control coordinates planes to avoid direct plane-to-plane communication.
Seeing this real-world system helps grasp the importance of centralized coordination in complex environments.
Message broker systems
Mediator pattern in software is similar to message brokers in distributed systems that route messages between services.
Knowing this connection helps understand how design patterns scale from simple objects to large distributed architectures.
Common Pitfalls
#1Making the mediator handle too many responsibilities.
Wrong approach:class Mediator { void handleAllLogic() { // All business logic and communication } }
Correct approach:class Mediator { void coordinateCommunication() { // Only route messages, delegate logic to components } }
Root cause:Confusing the mediator's role with business logic leads to bloated, hard-to-maintain mediators.
#2Components still tightly coupled by calling each other directly.
Wrong approach:componentA.callMethodOn(componentB);
Correct approach:mediator.notify(componentA, event);
Root cause:Not fully adopting the mediator pattern keeps dependencies and defeats decoupling.
#3Using a single mediator for too many components without layering.
Wrong approach:One mediator class managing hundreds of components directly.
Correct approach:Multiple mediators organized hierarchically, each managing a subset of components.
Root cause:Ignoring scalability leads to mediator bottlenecks and complexity.
Key Takeaways
The Mediator pattern centralizes communication to reduce direct dependencies between components.
It simplifies system design by making components unaware of each other, only interacting through the mediator.
Overloading the mediator with too much logic creates a 'God object' anti-pattern that harms maintainability.
In large systems, mediators should be organized hierarchically to handle scale effectively.
Understanding when and how to use the mediator pattern helps build flexible, maintainable, and scalable systems.