🧠 Introduction: What is the Mediator Pattern?
The Mediator Pattern is a behavioral design pattern that promotes loose coupling by ensuring that instead of components referring to each other explicitly, they interact through a central mediator object.
In essence, the mediator acts as an intermediary between objects, handling communication and coordination, which simplifies dependencies and makes the system more maintainable.
✨ Why Use It?
- To reduce tight coupling between classes.
- To centralize control of complex communication logic.
- To improve maintainability, especially in UI-heavy or event-driven systems.
🧩 Core Intent and Participants
Intent: Define an object that encapsulates how a set of objects interact. Promotes loose coupling by keeping objects from referring to each other explicitly.
Participants:
Mediator
– Interface that defines communication methods.ConcreteMediator
– Implements mediator logic and maintains references to Colleagues.Colleague
– Components that communicate through the mediator.
interface Mediator {
void send(String message, Colleague colleague);
}
abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
class ConcreteMediator implements Mediator {
private ColleagueA colleagueA;
private ColleagueB colleagueB;
public void setColleagueA(ColleagueA a) { this.colleagueA = a; }
public void setColleagueB(ColleagueB b) { this.colleagueB = b; }
public void send(String message, Colleague sender) {
if (sender == colleagueA) {
colleagueB.receive(message);
} else {
colleagueA.receive(message);
}
}
}
💡 Real-World Use Cases
Scenario | Description |
---|---|
Chat Apps | Messages go through a central chat server (mediator) rather than user-to-user directly. |
Air Traffic Control | Each plane communicates with the tower, not with other planes directly. |
UI Components | A dialog box with components like text fields and buttons, coordinating through a mediator. |
Workflow Engines | Where tasks trigger others indirectly through a central controller. |
🛠️ Implementation in Java
Let’s build a simple chatroom where users communicate via a ChatMediator
.
interface ChatMediator {
void showMessage(String message, User user);
}
class ChatRoom implements ChatMediator {
public void showMessage(String message, User user) {
System.out.println(user.getName() + ": " + message);
}
}
class User {
private String name;
private ChatMediator mediator;
public User(String name, ChatMediator mediator) {
this.name = name;
this.mediator = mediator;
}
public String getName() { return name; }
public void send(String message) {
mediator.showMessage(message, this);
}
}
✅ Demo
public class Main {
public static void main(String[] args) {
ChatMediator mediator = new ChatRoom();
User alice = new User("Alice", mediator);
User bob = new User("Bob", mediator);
alice.send("Hi Bob!");
bob.send("Hey Alice!");
}
}
Output:
Alice: Hi Bob!
Bob: Hey Alice!
✅ Pros and Cons
✅ Pros
- Promotes loose coupling.
- Centralizes complex communication logic.
- Simplifies maintenance and debugging.
❌ Cons
- Mediator can become a God object if overused.
- Can introduce single point of failure.
❌ Anti-patterns and Misuse
- Too much logic in the Mediator — violates SRP (Single Responsibility Principle).
- Overuse for simple communication between two classes.
🆚 Comparison with Other Patterns
Pattern | Key Difference |
---|---|
Observer | One-to-many broadcast. |
Mediator | Central coordination of many-to-many interactions. |
Facade | Simplifies subsystem interface, but doesn’t coordinate components’ behavior. |
🧼 Refactoring Legacy Code
If your code has too many tightly coupled components, extract a Mediator
to reduce dependencies and centralize coordination logic.
Before:
button.setOnClick(() -> textField.disable());
After:
Use mediator to orchestrate behavior between Button
, TextField
, and Dialog
.
🧠 Real-World Analogy
Think of an event planner managing a wedding. The caterers, decorators, and musicians don't talk to each other — they coordinate through the planner.
🧠 Java Version Relevance
Modern Java (post Java 8) makes this pattern even more elegant using lambdas and functional interfaces for callback handling in the mediator.
🧠 Best Practices
- Use for complex interaction between components.
- Avoid turning mediator into God object.
- Define a clear protocol of communication.
✅ Conclusion & Key Takeaways
- Use the Mediator Pattern to reduce class interdependencies.
- Great for event-driven, GUI, or workflow-based systems.
- Clean, centralized control boosts maintainability.
❓ FAQ
1. What is the main purpose of the Mediator Pattern?
To simplify and centralize complex communication between objects.
2. How does it promote loose coupling?
Colleagues don’t refer to each other directly — they go through the mediator.
3. When should I use this pattern?
When you have complex many-to-many object interaction.
4. Is it similar to the Observer pattern?
No — Observer is one-to-many; Mediator is many-to-many with a central point.
5. Can it be used in UI frameworks?
Absolutely. It’s very common in GUI logic (e.g., dialogs).
6. What’s the risk of using this pattern?
Your mediator becoming too big and hard to manage.
7. What’s the difference between Mediator and Facade?
Mediator coordinates behavior. Facade simplifies interface.
8. How does this apply to chat systems?
Users talk to a mediator (chatroom/server), not to each other directly.
9. Does this pattern affect performance?
Minimal — it's a control pattern, not resource-heavy.
10. Can I use lambdas with the mediator?
Yes! Functional interfaces can simplify interaction logic.