AcademyDesign Patterns
Mediator pattern
Routing communication between many objects through one hub, the god object the hub itself can become, and the temptation to route every interaction through it "to be safe."
5 min readUpdated 3 exercises
Mediator is for many-to-many communication: instead of every object holding references to every other object it needs to talk to, all of them talk through one shared go-between.
A Mediator adds a third object that every participant talks through, instead of participants holding direct references to each other. Where Observer lets many listeners find out about one subject, Mediator lets many peers talk to each other without any pair of them knowing the other exists.
The problem it solves
A form has a country select, a state select, a zip code field and a submit button. Picking a country changes which states are available, changes the zip code format, and enables or disables the button.
If each field talks to the others directly, every field needs a reference to several others:
- Connections multiply. Four components can have twelve one-way links. Add a fifth and it needs links to all four.
- Each component knows too much. The country select knows how the zip field validates, so it cannot be reused in another form.
- Changing a rule touches many files. "Some countries have no states" means editing three components.
The fix is to move the coordination into one object. Components report what happened to it and never talk to each other.
Structure
Three parts:
- The mediator interface: how participants report events.
- The concrete mediator (
ChatRoom): holds references to the participants and contains the coordination rules. - Participants (
User): each holds a reference to the mediator, not to each other.
class ChatRoom {
showMessage(user, message) {
return user.name + ': ' + message;
}
}
class User {
constructor(name, chatRoom) {
this.name = name;
this.chatRoom = chatRoom;
}
send(message) {
return this.chatRoom.showMessage(this, message);
}
}
// const room = new ChatRoom();
// const alice = new User('Alice', room);
// const bob = new User('Bob', room);
// alice.send('hi bob') → 'Alice: hi bob'Alice sends a message without knowing who is in the room. The room decides who gets it, and could later filter, log or reject it, without any user changing.
Where it is used in real systems
| Use case | The mediator |
|---|---|
| Chat rooms | Delivers messages between users without them holding each other's addresses. |
| Form coordination | One controller deciding how fields affect each other. |
| Air traffic control | Planes talk to the tower, never to each other. |
| UI dialogs | A dialog controller enabling buttons based on several inputs. |
| Event buses | A shared channel that components publish to and read from. |
| State stores | Redux and Pinia: components dispatch and read, and never call each other. |
| Microservice orchestration | A workflow service coordinating services that do not know about each other. |
Mediators you already use
- Redux and Pinia stores. Components do not call each other. They dispatch to a store, and the store decides what changes.
- Form libraries. React Hook Form and Angular's
FormGroupcoordinate several controls and their validation. - Message brokers. Kafka, RabbitMQ and SQS sit between services that do not know about each other.
- Air traffic control is the textbook example, and comes up in interviews.
- Angular services and Vue provide/inject used as a shared coordinator between sibling components.
Mediator or Observer
Both decouple objects and are easy to confuse.
| Observer | Mediator | |
|---|---|---|
| Direction | One subject to many listeners | Many peers, through one hub |
| Who knows what | Subject knows its listeners exist | Peers know only the mediator |
| Logic | In each listener | Centralized in the mediator |
| Communication | Broadcast | Routed, and can be filtered or transformed |
An event bus is often both: the observer pattern used to implement a mediator.
When not to use it
- It turns into a god object. All the coordination logic piles into one class, and the mediator becomes the hardest thing to change. Split it by feature.
- Two objects that talk to each other. A mediator between two components is just an extra hop.
- The relationships are simple. A parent that passes props and callbacks to a child does not need a mediator.
- It hides the flow. With everything routed through one place, it can be hard to see who triggers what. Keep the mediator's rules readable and tested.
What interviewers ask
- "What is the Mediator pattern?" A central object coordinating communication between others, so they do not reference each other.
- "Mediator versus Observer?" Observer broadcasts from one subject. Mediator routes between many peers and holds the coordination logic.
- "What is the downside?" The mediator can become a bloated god object.
- "Give a real example." A chat room, a form controller, or a Redux store.
- "Mediator versus Facade?" A Facade simplifies access to a subsystem and the subsystem does not know about it. A mediator is known to its participants, and they communicate through it.
The mistake to avoid
A Mediator that participants also bypass. If User objects sometimes call each other directly, the coordination rules in the room no longer apply to every message, and you have both the coupling and the extra hop. Make the mediator the only path, or do not use one.
The mechanism above, participants that hold a reference to one shared coordinator, is the same in JavaScript, Python or Java. Only the syntax changes.
Now practice it
1 challenge · 2 quizzesReading this page is the cheap half. These are the exercises that make you use it.
- MediatorProRoute messages between peers through a single hub and prove none of them hold a reference to each other — the N vs N² trade this page quantifies.ChallengeSolve · MediumChallengeSolve · Medium
- Design Patterns · Behavioral PatternsTen quick questions across Strategy, State, Observer, Command and the rest of the behavioral family, to check the mental model before this one.QuizTake · HardQuizTake · Hard
- Design Patterns · Architectural Patterns — Series 3ProA second, tougher pass on the same behavioral family, for once the first set feels easy.QuizTake · HardQuizTake · Hard
Read next
Observer pattern
Notifying many listeners without the subject knowing who they are, the leak a forgotten unsubscribe causes silently, and why every event system pairs subscribe with teardown.
5 min
Chain of Responsibility pattern
Trying handlers one at a time until one accepts the request, the dead end when a request reaches the last link unhandled, and why every chain needs a terminal case.
7 min