Skip to article
ALGORITHMICSPatterns
Patterns5 min read

Mediator

A hub instead of a mesh — and the risk that the hub becomes the program.


A booking form. Choosing a date filters the times. Choosing a time enables the guest count. Weekends require at least two guests. Submit stays disabled until all three are valid, and a warning appears when the party is too large for the slot.

What people write first

Each field talks to the fields it affects.

dateInput.onChange = () => {
timeSelect.setOptions(slotsFor(dateInput.value));
guestsInput.setMin(isWeekend(dateInput.value) ? 2 : 1);
submitButton.disabled = !isComplete();
warning.update();
};

Every field ends up knowing about every other. Five fields is up to ten relationships, and it is n(n1)/2n(n-1)/2 — a sixth field makes fifteen.

Wiring

10 connections, and it is n(n−1)/2: a sixth field makes 15. Each field must know about every other, so none of them can be reused or tested alone.

Worse than the count: no field can be tested, reused or moved on its own, because each one references the others by name.

The pattern

Fields report changes to one object. That object knows the rules.

class BookingForm {
constructor(
private readonly date: DateField,
private readonly time: TimeField,
private readonly guests: NumberField,
private readonly submit: Button,
) {
for (const field of [date, time, guests]) field.onChange = () => this.sync();
}
/** Every rule about how these fields relate, in one readable place. */
private sync() {
this.time.setOptions(slotsFor(this.date.value));
this.guests.setMin(isWeekend(this.date.value) ? 2 : 1);
this.submit.disabled = !(this.date.value && this.time.value && this.guests.valid);
}
}

Five connections instead of ten, and the fields are now generic — a DateField that names no other field can be used in any form.

Mediator or Observer?

They solve overlapping problems and the difference is directionality.

Choose by whether the coordination rules are worth writing down together. A form with cross-field validation: yes, mediator. A logging system: no, observer.

Where it already is

Air traffic control is the textbook example and a genuinely good one — aircraft do not negotiate with each other. In code: a Redux store, an XState machine coordinating services, a ViewModel in MVVM, and a chat server relaying between clients that never learn each other’s addresses.