Mediator Pattern
Mediator centralises conversation between colleagues.
Introduction
Mediator centralises conversation between colleagues. Instead of N×N direct connections, all talk through one Mediator that orchestrates interaction. Appears in UI form coordination, chat rooms, sagas/process managers, and MediatR-style command dispatch.
The story
A flight booking form had 14 fields with cross-cutting rules (round trip enables return date; infant adds parent dropdown). Each field listened to every other — adding a rule meant editing 13 listeners. FormMediator centralised rules; fields only told mediator something changed.
The business problem
N×N component coupling creates hairball graphs and fragile reuse:
- Listener explosion: each field listens to all others — 14² edges.
- Rule scatter: one new rule touches many components.
- Unreusable components: entangled with specific peers.
- Debug nightmare: cascade of callbacks with no central trace.
The problem teams faced
Mediator fits when:
- Many objects interact in complex ways.
- Adding interaction rule requires changing many objects.
- Components should not reference each other directly.
- Central coordinator owns conversation policy (form, saga, chat).
Understanding the topic
Intent: Encapsulate object interaction in Mediator; colleagues don't refer to each other.
- Mediator — interface for colleague communication.
- ConcreteMediator — owns rules; coordinates reactions.
- Colleague — knows Mediator only; notifies on change.
Internal architecture
Form mediator:
class BookingFormMediator {constructor(private tripType: SelectField,private returnDate: DateField,private passengerType: SelectField,private parentName: TextField,) {}onChange(source: Field, value: unknown) {if (source === this.tripType) {this.returnDate.setEnabled(value === "round-trip")}if (source === this.passengerType) {this.parentName.setVisible(value === "infant")}}}
Visual explanation
Three diagrams cover star topology, form mediator, and vs Observer:
Informative example
Before / after — peer listeners to Mediator:
// ❌ Each field listens to every other — 13 edits per new rulereturnDate.onChange(tripType.value)tripType.onChange(() => returnDate.enabled = tripType.value === "round-trip")passengerType.onChange(() => { /* 5 more peer updates */ })// ✅ Mediator owns all rulesclass FormMediator {onChange(field: Field, value: unknown) {if (field === this.tripType) {this.returnDate.setEnabled(value === "round-trip")}if (field === this.passengerType) {this.parentField.setVisible(value === "infant")}}}fields.forEach(f => f.onChange(v => mediator.onChange(f, v)))
Execution workflow
Map interactions
Draw which field affects which.
Real-world use
Air traffic control (literal mediator), chat rooms, UI form wizards, MediatR (.NET), saga/process managers in distributed systems, Redux reducer coordinating state slices (debated — shares coordination idea).
Production case study
Flight booking form:
- Scenario: 14 fields, each listening to all others for cross-rules.
- Decision: BookingFormMediator centralises enable/disable/visible rules.
- Outcome: New rule = one method edit; fields reusable in other forms.
Trade-offs
- Pro: reduces N² to N; rules in one place; reusable colleagues.
- Pro: easier to test interaction policy centrally.
- Con: Mediator can become god-object if unbounded.
- Con: indirection — harder to trace than direct calls for simple cases.
Decision framework
- Use when many components have complex mutual dependencies.
- Use for form wizards, sagas, chat coordination.
- Avoid when two components with simple callback — direct link fine.
- Split mediator when rules domains differ (billing vs shipping).
Best practices
- Colleagues notify mediator; never call peer directly.
- Split god-mediator by subdomain when rule count grows.
- Saga as Mediator for multi-step distributed workflows.
Anti-patterns to avoid
- God-mediator with business logic for entire application.
- Mediator for two-component parent-child — overkill.
- Mediator that becomes Facade — know the difference.
Common mistakes
- Mediator knows too much domain — split or push logic down.
- Circular notify loops if mediator triggers field that re-notifies.
Debugging tips
- Log mediator onChange with source field name and resulting actions.
- Unit test rule matrix — all field combinations.
Optimization strategies
- Debounce mediator reactions on rapid field changes (search forms).
Common misconceptions
- Mediator ≠ Facade. Mediator coordinates peers; Facade simplifies subsystem for external client.
- Saga is Mediator at workflow scale — coordinates services via events/commands.
- Observer broadcasts; Mediator orchestrates multi-party rules.
Advanced interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1IntermediateQuestionMediator vs Observer?+
Answer
Follow-up
2AdvancedQuestionMediator vs Facade?+
Answer
Follow-up
3AdvancedQuestionSaga as Mediator?+
Answer
Follow-up
4BeginnerQuestionWhen Mediator overkill?+
Answer
Follow-up
Summary
You can extract FormMediator from listener hairballs and recognize sagas as distributed Mediators. Tell the 14-field flight booking story — if you can do that, you own Mediator.