What is the Mediator Pattern?
The Mediator Pattern is a behavioral design pattern that:
Centralizes communication between multiple objects, preventing them from referring to each other explicitly and reducing dependencies.
Instead of components talking to each other directly, they communicate through a mediator, leading to better modularity and reduced coupling.
Real-World Analogy
Think of an air traffic controller:
- Planes don’t talk to each other directly.
- They communicate through the air traffic control tower (the mediator), which coordinates their actions.
When to Use
- You have many components interacting in complex ways.
- You want to reduce tight coupling between classes.
- You want to centralize logic that would otherwise be scattered across objects.
Benefits
| Benefit | Description |
|---|---|
| Decouples Components | Objects don’t talk to each other directly |
| Improves Maintainability | Centralized interaction logic simplifies code changes |
| Easier to Extend | Add new components without altering others |
Drawbacks
- Mediator can become a “god object” if it grows too complex.
- May introduce performance bottlenecks in large systems.
Dart Example: Chat Room Mediator
We’ll build a mini chat room where users send messages to each other through a central mediator.
Step 1: Define the Mediator Interface
abstract class ChatRoomMediator {
void sendMessage(String message, User user);
}
Step 2: Create Concrete Mediator
class ChatRoom implements ChatRoomMediator {
final List<User> _users = [];
void register(User user) {
_users.add(user);
}
@override
void sendMessage(String message, User sender) {
for (var user in _users) {
if (user != sender) {
user.receive(message, sender.name);
}
}
}
}
Step 3: Create User Class
class User {
final String name;
final ChatRoomMediator chatRoom;
User(this.name, this.chatRoom);
void send(String message) {
print("$name sends: $message");
chatRoom.sendMessage(message, this);
}
void receive(String message, String senderName) {
print("$name receives from $senderName: $message");
}
}
Step 4: Client Code
void main() {
final chatRoom = ChatRoom();
final alice = User("Alice", chatRoom);
final bob = User("Bob", chatRoom);
final charlie = User("Charlie", chatRoom);
chatRoom.register(alice);
chatRoom.register(bob);
chatRoom.register(charlie);
alice.send("Hello everyone!");
bob.send("Hey Alice!");
}
Output
Alice sends: Hello everyone!
Bob receives from Alice: Hello everyone!
Charlie receives from Alice: Hello everyone!
Bob sends: Hey Alice!
Alice receives from Bob: Hey Alice!
Charlie receives from Bob: Hey Alice!
Use Cases in Dart & Flutter
- Dialog interactions in Flutter (instead of widgets communicating directly).
- UI component coordination (e.g. sliders, text fields affecting each other).
- State machines where transitions are managed centrally.
- Widget communication in MVVM (via ViewModel as mediator).
Summary
| Property | Value |
|---|---|
| Type | Behavioral |
| Intent | Centralize object interaction |
| Avoids | Tight coupling between objects |
| Common In | Chat systems, UI coordination |
Mediator vs Observer vs Command
| Pattern | Key Idea |
|---|---|
| Mediator | Centralizes communication among components |
| Observer | Broadcasts changes to many subscribers |
| Command | Encapsulates requests as objects, doesn’t manage coordination logic |



