In software systems, multiple objects often need to communicate with each other. If each object talks directly to every other object, the system becomes tangled and hard to maintain. This is known as object spaghetti.
The Mediator Pattern solves this by centralizing communication logic in a mediator
object, promoting loose coupling and better maintainability.
๐จโ๐ซ Intent
Define an object that encapsulates how a set of objects interact. The mediator promotes loose coupling by keeping objects from referring to each other explicitly.
๐ฆ Real-World Analogy
Think of an Air Traffic Controller (Mediator). Planes (Colleagues) do not communicate with each other directly โ they all communicate via the ATC, which coordinates safe takeoffs and landings.
๐งฐ UML Diagram
๐ก When to Use
- When a set of objects communicate in complex but well-defined ways
- When reusability of objects is difficult due to tight coupling
- When you want to centralize control logic
๐งช C# Example
// Mediator interface
public interface IChatMediator {
void SendMessage(string message, User user);
}
// Concrete mediator
public class ChatRoom : IChatMediator {
private List<User> users = new();
public void RegisterUser(User user) {
users.Add(user);
}
public void SendMessage(string message, User sender) {
foreach (var user in users) {
if (user != sender) {
user.Receive(message);
}
}
}
}
// Colleague
public class User {
private string name;
private IChatMediator chatMediator;
public User(string name, IChatMediator mediator) {
this.name = name;
this.chatMediator = mediator;
}
public void Send(string message) {
chatMediator.SendMessage(message, this);
}
public void Receive(string message) {
Console.WriteLine($"{name} received: {message}");
}
}
class ChatRoom:
def __init__(self):
self.users = []
def register_user(self, user):
self.users.append(user)
def send_message(self, message, sender):
for user in self.users:
if user != sender:
user.receive(message)
class User:
def __init__(self, name, mediator):
self.name = name
self.mediator = mediator
def send(self, message):
self.mediator.send_message(message, self)
def receive(self, message):
print(f"{self.name} received: {message}")
# Usage
room = ChatRoom()
alice = User("Alice", room)
bob = User("Bob", room)
room.register_user(alice)
room.register_user(bob)
alice.send("Hello Bob!")
โ Benefits
- Reduces direct dependencies between objects
- Makes it easier to modify or extend interactions
- Centralized control makes debugging and testing easier
โ ๏ธ Drawbacks
- Mediator can become overly complex if it handles too many interactions
- Can introduce a performance bottleneck
๐ Real-World Use Cases
- Chat room systems
- UI component interaction coordination (e.g., MVC Controllers)
- Air Traffic Control systems
๐ง Quiz Yourself
Test your understanding with our interactive Mediator Pattern quiz.
๐ Summary
- Mediator pattern reduces object coupling
- Useful in systems where multiple objects interact in defined ways
- Encourages clean architecture and better maintainability