Behavioral · Gang of Four
Mediator
Mediator is a behavioral pattern that routes conversation among peer objects through one hub. Widgets talk to the mediator, not to each other — so adding a field does not rewire every other widget.
Example: a booking dialog with a name field, date picker, OK button, and error label. Without a mediator, the button asks the field if it is empty, the field asks the date if it is past, and every widget imports every other widget. The hub enables OK when the fields agree.
Interview checks before you name it
- Do OK, Name, and Date need to know each other’s rules? If yes, Mediator.
- Do Scoreboard and Stats only need a Goal event? If yes, Observer — do not call it Mediator.
- Is BookingService a door for outsiders into payments + inventory? That is Facade, not a hub among peers.
- If the hub also charges the card and emails the receipt, split those colleagues out.
Before: pairwise mesh
Six arrows you cannot draw without overlapping. That is the smell.
After: one hub
Each has one import: the dialog.
The contrast people mix up
Observer vs Mediator
Observer is one-to-many news: a subject shouts “goal scored” and does not care who listens. Listeners do not coordinate with each other through the subject. Mediator is many-to-many traffic control: the hub knows the colleagues and directs the chat. If Scoreboard, Stats, and Clipper only need a Goal event, that is Observer. If OK, Name, and Date must enable and disable each other, that is Mediator.
Observer · one-to-many news
- Subject holds a list of Observer
- Notify is fire-and-forget
- Listeners do not talk through the subject
- New listener: new class, subject unchanged
Mediator · many-to-many traffic
- Hub knows the colleagues by role
- changed() is “figure out who to update”
- Colleagues stay reusable; the dialog is specific
- New field: edit the hub, not every widget
You can even have a mediator that is also a subject, but say which job you are using. News versus traffic control.
Facade is a different door
Facade is a simple door into a subsystem for outsiders. Mediator sits among peers and runs their conversation. Do not call a BookingService facade a mediator because it has three collaborators.
Keep the hub from becoming a God object
A that persists, prices, and emails has left traffic control. When the dialog grows a payment step, that step is another colleague. See collaboration.
Java: widgets talk only to the dialog
TextField does not import DatePicker. Button does not import TextField. The hub’s changed() is allowed to know everyone — that is the trade: one specific class so many widgets stay dumb.
class BookingDialog {
private final TextField name = new TextField(this);
private final DatePicker date = new DatePicker(this);
private final Button ok = new Button(this);
void changed(Widget source) {
boolean ready = !name.isBlank() && date.isFuture();
ok.setEnabled(ready);
}
}
class TextField {
private final BookingDialog dialog;
TextField(BookingDialog dialog) { this.dialog = dialog; }
void type(String text) {
this.value = text;
dialog.changed(this);
}
}
class DatePicker {
private final BookingDialog dialog;
DatePicker(BookingDialog dialog) { this.dialog = dialog; }
void pick(LocalDate d) {
this.value = d;
dialog.changed(this);
}
}Widgets that still import each other
Calling Observer a Mediator
Walk of a keystroke
User types a letter in Name. TextField stores it, then calls dialog.changed(this). The hub reads name and date, then enables or disables OK and maybe sets an error label. No widget asks another widget. That is the whole runtime story.
- 1TextField.type → dialog.changed(this)
- 2Dialog reads name.isBlank() and date.isFuture()
- 3Dialog calls ok.setEnabled(ready)
- 4Dialog may set error.setText(...) — still the hub, not the field
Chat room is the other picture
Users do not hold a list of every other user. They send to the room; the room fans out. That hub is a mediator. If the room only shouts “message posted” and does not coordinate members, you have slid into Observer. Say which job you mean.
Air-traffic control
Planes do not negotiate pairwise. The tower sequences them. Colleagues stay simple; the hub is allowed to be specific. When the hub also fuels the planes, it became a God object.
Java: guest count as another colleague
Adding a field edits BookingDialog.changed, not TextField. That is the proof the mesh is gone.
void changed(Widget source) {
boolean ready = !name.isBlank() && date.isFuture() && guests.inRange();
ok.setEnabled(ready);
error.setVisible(!ready);
}How to explain this in an interview
“Widgets will not import each other. The dialog owns the conversation.” If they then ask about a Goal event, switch vocabulary to Observer. Mixing the names is the usual fail.
Facade is a door for outsiders. Mediator sits among peers. A BookingService that hides payments is Facade. A BookingDialog that enables OK is Mediator. Keep the hub from booking the hotel itself.
- Cut pairwise imports or the hub is decoration.
- A new guest-count field edits the dialog, not every widget.
- If Button still calls name.isBlank(), stop and cut the import.
- News (one-to-many) is Observer; traffic control is this page.
Name the job: traffic control, not news.
Nearby in LLD