What Problem Does Mediator Solve?
When many objects need to interact — a chat room with dozens of users, or a UI form with interdependent widgets — letting each object hold direct references to every other object it might need to talk to creates a tangled web of many-to-many dependencies. The Mediator pattern introduces a single object, the Mediator, through which all these interactions are routed. Colleague objects no longer talk to each other directly; instead they notify the mediator of events, and the mediator decides how to react and which other colleagues to notify. This converts an O(n²) web of relationships into a simpler hub-and-spoke structure centered on the mediator.
Cricket analogy: An IPL auction doesn't have all ten franchises negotiating directly with every player; instead the auctioneer acts as a mediator, receiving bids and announcing results, collapsing what could be chaotic many-to-many haggling into a single controlled channel.
Structure: Mediator and Colleagues
The pattern defines a Mediator interface with a method like notify(sender, event), and one or more ConcreteMediator classes that implement the coordination logic. Colleague classes hold a reference to the mediator (often injected via constructor) and call mediator.notify(this, 'someEvent') whenever something noteworthy happens, rather than calling other colleagues directly. The ConcreteMediator's notify() implementation contains a switch or if-chain that decides, based on the sender and event type, which other colleagues to invoke and how. This concentrates business logic that would otherwise be scattered across many classes into one place, which aids readability but can make the mediator itself grow large and become a god object if not kept disciplined.
Cricket analogy: A DRS review protocol has fielders and the bowler alert the umpire (the mediator) with the event 'review requested', and the umpire alone decides whether to escalate to the third umpire and how to relay the final decision back to the players.
interface Mediator {
notify(sender: object, event: string): void;
}
class DialogMediator implements Mediator {
constructor(
private submitButton: Button,
private nameField: TextField,
private emailField: TextField
) {}
notify(sender: object, event: string): void {
if (sender === this.nameField && event === 'changed') {
this.submitButton.setEnabled(
this.nameField.value.length > 0 && this.emailField.value.includes('@')
);
}
if (sender === this.emailField && event === 'changed') {
this.submitButton.setEnabled(
this.nameField.value.length > 0 && this.emailField.value.includes('@')
);
}
}
}
class TextField {
value = '';
constructor(private mediator: Mediator) {}
onChange(value: string) {
this.value = value;
this.mediator.notify(this, 'changed');
}
}
class Button {
setEnabled(enabled: boolean) {
console.log(`Submit button enabled: ${enabled}`);
}
}Mediator vs. Observer
Mediator and Observer are often used together but solve slightly different problems. Observer establishes a one-to-many broadcast: a subject notifies all subscribed observers whenever its state changes, and any observer can subscribe without the subject knowing who they are. Mediator instead centralizes many-to-many coordination logic between a fixed, known set of colleagues, and the mediator actively decides what happens next rather than passively broadcasting. In practice, a ConcreteMediator is often implemented using Observer internally — colleagues 'observe' the mediator and the mediator 'observes' each colleague — but the conceptual distinction is that Mediator's job is to encapsulate decision-making logic about interactions, while Observer's job is purely notification.
Cricket analogy: A stadium's PA announcer broadcasting the score to every fan (nobody chosen, anyone in earshot receives it) is Observer, whereas the on-field captain deciding field placements by talking to specific fielders is Mediator, actively coordinating a known set of players.
GUI frameworks are one of the most common places to find Mediator in practice: a dialog controller class often mediates between form fields, validation messages, and a submit button, exactly as shown in the code example above.
Because a mediator concentrates coordination logic, an undisciplined implementation can balloon into a god object that knows too much about every colleague's internals. Mitigate this by splitting responsibilities across multiple smaller mediators for distinct concerns rather than one mediator for an entire application.
- Mediator centralizes communication between colleague objects, replacing many-to-many references with a hub-and-spoke structure.
- Colleagues notify the mediator of events; they don't call each other directly.
- The ConcreteMediator's notify() method contains the coordination logic deciding how colleagues respond to each other's events.
- Mediator reduces coupling and makes colleague classes more reusable in isolation.
- Mediator differs from Observer: Observer is passive one-to-many broadcast, Mediator actively coordinates a known set of participants.
- A poorly scoped mediator risks becoming a god object; splitting into multiple focused mediators helps.
- GUI form validation coordinating multiple fields and a submit button is a textbook real-world example.
Practice what you learned
1. What is the main structural change the Mediator pattern introduces?
2. How do colleague objects typically interact with each other under the Mediator pattern?
3. What is a key conceptual difference between Mediator and Observer?
4. What is a common risk of implementing Mediator poorly?
5. In a GUI form example, what role does the mediator typically play?
Was this page helpful?
You May Also Like
Chain of Responsibility Pattern
A behavioral pattern that passes a request along a chain of handlers until one of them handles it, decoupling senders from receivers.
Iterator Pattern
A behavioral pattern that provides a way to access elements of an aggregate object sequentially without exposing its underlying representation.
Memento Pattern
A behavioral pattern that captures and externalizes an object's internal state so it can be restored later, without violating encapsulation.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringSoftware Engineering Study Notes
Python · 40 topics
Software EngineeringGit & Version Control Study Notes
Bash · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics