skip to content

questions

5

What is the intent of the Mediator design pattern, and what kind of coupling problem does it address?

level: juniorimportance: must knowfreq 62%

answer

  1. Colleagues know only the mediator
  2. Mesh N*(N-1) → star N links
  3. Protocol lives in one named place
  4. Dialog box: fields report, dialog decides
  5. Cost: god-object + indirection

basics

~20 s

Mediator defines one object that encapsulates how a group of objects interact. Instead of each object calling the others directly, they all talk to the mediator. That turns tangled many-to-many links into simple one-to-many links.

solid answer

~40 s

Mediator is a behavioral pattern whose intent is to "define an object that encapsulates how a set of objects interact". The interacting objects are called colleagues. Without a mediator, each colleague holds references to the colleagues it must notify, so N collaborating objects can approach N*(N-1) directed links — a many-to-many web where every new colleague touches existing ones. With a mediator, each colleague knows only the mediator; the mediator knows all colleagues and holds the interaction rules. Coupling drops from many-to-many to many-to-one (a star topology), colleagues become individually reusable and unit-testable, and the interaction protocol becomes explicit and changeable in one place rather than being smeared across participants. The classic example is a dialog box: fields do not enable/disable each other; they report changes to the dialog, which applies the rules.

code

pseudocode · 16 lines
pseudocode
interface Mediator { notify(sender, event) }

class FormMediator implements Mediator {
  country; state; postal; submit
  notify(sender, event) {
    if (sender == country && event == "changed") {
      state.reloadFor(country.value); postal.clear()
    }
    submit.enabled = country.valid && state.valid && postal.valid
  }
}

class Dropdown {
  mediator
  onChange() { mediator.notify(this, "changed") }   // knows nobody else
}

go deeper

for a junior

State the intent (one object encapsulates how a set of objects interact), name colleague and mediator, and give the dialog-box or chat-room example.

for a middle

Add the coupling arithmetic (mesh vs star), the participant roles including the abstract Mediator interface, and contrast with Observer and Facade.

for a senior

Discuss when it is worth it: rules-heavy interaction, several colleagues, frequent protocol change — plus the god-object cost and how you keep the mediator small.

for a principal

Frame it as a topology decision that recurs at every scale (UI controller, service orchestrator, message broker, service mesh) and reason about when centralizing a protocol creates a bottleneck or single point of failure.

## The problem Imagine a set of objects that must react to each other. A form has a country dropdown, a state dropdown, a postal-code field, and a Submit button. The rules are: choosing a country reloads the state list, clearing state clears postal code, and Submit is enabled only when all are valid. The naive implementation gives each widget references to the widgets it must poke: the country dropdown calls `stateList.reload()` and `submit.recheck()`, the state dropdown calls `postal.clear()` and `submit.recheck()`, and so on. Two consequences follow: 1. **Coupling explodes.** Any colleague may need a reference to any other, so the number of possible directed links grows quadratically — N*(N-1) for N colleagues. Adding a new field means editing several existing ones. 2. **The protocol becomes invisible.** The rule "changing country clears the postal code" does not live anywhere; it is an emergent property of scattered calls. Nobody can read the interaction as a whole, and nobody can change it safely. Colleagues also stop being reusable: the state dropdown cannot be dropped into another form because it hard-references *this* form's postal field. ## The pattern **Mediator** (Gang of Four, behavioral) introduces one object that owns the interaction: - **Mediator** — an interface declaring how colleagues report events, classically a single `notify(sender, event)` method (GoF calls it `ChangeAware`/`WidgetChanged`; modern code often names it `notify`, `handle`, or `dispatch`). - **ConcreteMediator** — implements the interaction logic; holds references to all colleagues and coordinates them. - **Colleague** — each participating object; holds a reference to the mediator only. When something interesting happens it calls `mediator.notify(this, event)` and lets the mediator decide who else must react. Topology changes from a **mesh** to a **star**: N colleague→mediator links instead of up to N*(N-1) colleague→colleague links. ## What you actually gain - **Single Responsibility.** Interaction rules move out of the participants into one class that has a name and can be read top to bottom. - **Open/Closed for colleagues.** Adding a colleague changes the mediator, not the other colleagues. - **Reusability.** A colleague depends on an abstract mediator interface, so it can be used in any context that supplies one. - **Testability.** Colleagues can be tested against a stub mediator; the mediator can be tested against stub colleagues, and the protocol assertions live in one test suite. ## What you pay - **God-object risk.** All the interaction logic converges on one class. Unchecked, the mediator becomes a huge, high-churn class that knows every colleague — you traded a distributed mess for a centralized one. - **Indirection.** Reading the flow requires a hop through the mediator; stack traces and "who called this?" navigation get longer. - **Not a decoupling of *knowledge*, only of *references*.** The mediator still knows every colleague; complexity is relocated, not deleted. ## Boundaries with neighbours - **Observer** decouples a subject from unknown subscribers via broadcast; a mediator knows its colleagues by name and applies *rules* between them. Many mediators are *implemented* using observer-style subscriptions. - **Facade** simplifies access to a subsystem for outside callers, and the subsystem does not know the facade; mediator members *do* know and call the mediator, and communication is bidirectional. - **Command** encapsulates a single request as an object; Mediator encapsulates the whole conversation. ## Rule of thumb Reach for Mediator when the interaction rules — not the individual behaviours — are the complicated part, and when you find yourself editing several classes to change one rule. Skip it when only two objects talk, or when the interaction is a simple broadcast (plain Observer is lighter).

  • How is Mediator different from Facade, since both add an object in front of a group of objects?
    Direction and awareness. A facade is a one-way convenience entry point for *external* clients; the subsystem classes do not know the facade exists and keep talking to each other. With a mediator the participants explicitly depend on it and communication is bidirectional — they report to it and it calls them back — because its job is to own the interaction protocol, not to simplify an API surface.
  • Does Mediator reduce total system complexity?
    No — it relocates it. The number of interaction rules is unchanged; they are moved from many colleagues into one place where they are visible and editable. The win is comprehensibility and localized change, not less logic. If the mediator is left to grow unbounded, you get a single god object instead of a distributed mess.

Air-traffic control. Pilots do not negotiate landing order with each other over the radio — that would be N*(N-1) conversations and chaos. Each pilot talks only to the tower; the tower knows every aircraft and owns the sequencing rules.

context

open as a page

How does the Mediator pattern differ from the Observer pattern, and when would you choose one over the other?

level: middleimportance: must knowfreq 55%

basics

~20 s

Observer broadcasts an event to subscribers the sender does not know; it carries no rules about who reacts. Mediator is a named object that knows all participants and decides what each should do. Observer is notification; Mediator is coordination.

open as a page

The Mediator pattern's own well-known liability is that the mediator can become a god object. How does that happen, and what concrete techniques keep it from happening?

level: seniorimportance: must knowfreq 45%

basics

~20 s

Every new interaction rule gets added to the one mediator, so it grows a branch per case until it knows everything and everyone edits it. Fixes: split by cohesive interaction area, keep it routing-only with logic in colleagues, and use typed handlers instead of one giant switch.

open as a page

What code smells indicate that a group of collaborating classes should be refactored to introduce a Mediator, and when would introducing one be the wrong call?

level: middleimportance: should knowfreq 35%

basics

~20 s

Introduce a mediator when classes hold references to many siblings, one rule change forces edits in several of them, and reuse is impossible because each object hard-references the others. Skip it when only two objects talk or reactions are independent broadcasts.

open as a page

Where does the Mediator idea reappear at architecture scale, and what changes about the trade-offs when the colleagues are separate services instead of objects in one process?

level: principalimportance: should knowfreq 30%

basics

~20 s

The same star topology appears as orchestrators, workflow/saga coordinators, message brokers, API gateways, and enterprise service buses. Across services the centralizer also becomes an availability, scaling, and ownership bottleneck — not just a code-cohesion problem.

open as a page