Skip to content

Mediator Pattern: Talk to the Hub, Not to Each Other

Objects stop calling each other directly and go through one coordinator, so n objects need n links instead of n x (n - 1).

Builds on Coupling and Cohesion and Observer Pattern: Event-Driven Communication

Stage 3advanced9 min read

What is it?

Mediator is for a group of objects that all need to react to each other. Say every object keeps a reference (a link) to every other object. That gets messy fast. With Mediator, each object keeps just one link, to the mediator. An object tells the mediator what happened. The mediator decides who else needs to know and what they should do.

  • The objects in the group are called colleagues. The word is odd. It just means "a member of the group that talks through the hub".
  • The hub in the middle is the mediator. It holds the rules about who reacts to what.

Colleagues do not know about each other. They only know the mediator.

Real-life analogy

Bengaluru airport (BLR) at 8 am. IndiGo, Air India, Akasa and SpiceJet flights are all trying to land on the same runway.

The pilots do not radio each other to say "I am landing, you wait". With ten planes in the air, that would be chaos. Every pilot talks to the control tower. The tower knows who is on the runway, who is holding (circling and waiting), and who lands next. A pilot needs only one radio frequency.

The tower is the mediator. The flights are the colleagues.

The problem

Without a tower, each flight needs a list of all the other flights:

4 flights  ->  4 x 3  = 12 links
10 flights ->  10 x 9 = 90 links

That is n x (n - 1), and it grows fast. The count is not even the worst part:

  • The rule is copied into every flight. "Do not land if someone is on the runway" lives inside Flight. If the airport opens a second runway, you must edit the class every flight shares, and you hope nothing breaks.
  • Nobody owns the queue. When the runway clears, which waiting flight goes next? Each flight knows only about itself, so all of them keep asking. That is polling (asking again and again). Two flights can both think it is their turn.
  • Adding a flight touches everyone. A new flight goes into every existing flight's list, and every existing flight goes into its list.
  • Hard to test. To test one flight landing, you must build and wire all the others.

UI code has the same problem. On a Zomato checkout page, a coupon changes the total. The total decides if the wallet covers it. The wallet decides if the payment picker shows. The payment picker decides if the "Place order" button is enabled. If each widget calls the others directly, you get a tangled web of listeners that nobody wants to touch.

Class diagram

Loading diagram…

Every flight has one outgoing arrow, to the tower. No flight stores another flight.

Be precise about the reference count. Without a mediator, n flights that all link to each other hold n × (n - 1) peer references: 10 flights hold 90. With a mediator, the flights hold n references to the tower. The tower also needs references back to flights, so it can queue them and call them. So the total is not only n. In this sample the tower holds one onRunway reference plus up to n queue entries. The win is that flights no longer know each other, and one class owns all the links back. References are not free.

Components

PartIn our exampleJob
MediatorControlTowerThe interface (list of methods) colleagues call when something happens.
Concrete mediatorBengaluruTowerHolds the rules and the state (who is on the runway, who is waiting).
ColleagueFlightKnows only the mediator. Reports events and follows instructions.
ClientMainCreates the tower, then creates flights with a reference to it.

One call, step by step

AI-803 is holding. 6E-512 leaves the runway.

Loading diagram…

How it fixes each problem

ProblemWith Mediator
n x (n - 1) peer referencesn flight-to-tower references. The tower keeps its own references to the active and queued flights
Runway rule copied into every flightLives in BengaluruTower only
Nobody owns the waiting orderThe tower keeps a FIFO queue and hands out the runway
New flight means rewiring all flightsNew flight just gets the tower in its constructor
Testing needs every flightTest the tower with two flights, or test a flight with a fake tower

Mediator vs Observer vs Facade

All three put something in the middle. What the middle thing does is different.

MediatorObserverFacade
DirectionTwo way. Colleagues call it, and it calls them back.One way. The subject pushes events to subscribers.One way. The client calls in. The subsystems do not call back.
Who knows the rulesThe mediator. It decides who does what next.Each subscriber decides how to react on its own.The facade, but only to make calls simpler, not to coordinate peers.
Do the parts know about it?Yes, every colleague holds the mediator.The subject holds a list of observers. Observers may not know each other.No. Subsystem classes have no idea a facade exists.
Typical exampleAir traffic tower, chat room serverSwiggy order status pushing to app, SMS and the restaurantA BookingFacade over IRCTC search, seat, payment and PNR services

A short way to say it: Observer broadcasts, Facade simplifies, Mediator coordinates.

They can also be combined. A mediator often uses Observer inside, to get notified by its colleagues.

Real-world places you've seen it

  • Chat apps. On WhatsApp or Slack, your phone does not connect to every member of a group. It sends the message to the server. The server delivers it to the others.
  • Spring MVC's DispatcherServlet. It coordinates HandlerMapping, HandlerAdapter and ViewResolver beans. None of those beans call each other. The servlet passes the result from one to the next. (It is usually filed under Front Controller, which is also true. The way it sits between its helper beans is Mediator.)
  • java.util.Timer and ExecutorService. These show up on many lists of JDK Mediator examples. Treat them as a loose fit. Tasks hand themselves to the scheduler, which decides when and on which thread they run. But the tasks never talk to each other through it, and that is what makes a real mediator.
  • GUI dialogs. The original Gang of Four example is a font dialog where a list, a text field and buttons update each other through a director object.
  • Ride and delivery dispatch. On Uber or Swiggy, a dispatch service matches the rider with a driver (or the customer with a delivery partner). Neither side searches for the other.

Pros and cons

Pros

  • Colleagues are loosely coupled (they depend little on each other). You can reuse a Flight with a different tower.
  • All the interaction rules live in one place, so they are easy to read and change.
  • Adding a colleague does not touch the existing ones.
  • Many-to-many links become one-to-many, which is much easier to follow.

Cons

  • The mediator can grow into a God class (one class that knows and does everything). This is the big one.
  • It is a single point of failure. If the tower logic has a bug, every flight is affected.
  • Every interaction takes one extra hop, so simple flows are harder to trace in a debugger.

When to use

  • A group of objects talks to each other in tangled ways, and you keep adding direct references between them.
  • You cannot reuse a class because it depends on too many sibling classes.
  • The interaction rules change often and you want them in one place (checkout forms, booking flows, game lobbies).

When not to use

  • Only two objects interact. A direct call is clearer.
  • The relationship is really "one thing changed, tell whoever cares". That is Observer, and it is simpler.
  • You just want a simpler API over a messy library. That is Facade.

A mediator pays off when three or more parts react to each other and the rules between them keep changing. With fewer parts, it is extra ceremony. It also has a cost. A flow used to read "A calls B". Now it reads "A tells the hub, the hub checks its state, the hub calls B". The hub also becomes the one file every feature edits. If that file grows every sprint, split it before the whole team is stuck waiting on it.

Common mistakes

  • Letting the mediator do the colleagues' work. The tower decides who lands. It should not fly the plane. Keep the real work (domain logic) in the colleagues. The mediator only coordinates.
  • One mediator for the whole app. Split by area: a checkout mediator, a cart mediator. One giant mediator is just the old tangled code in a single file.
  • Colleagues still calling each other "just this once". One direct call and the coupling is back. Send everything through the mediator.
  • Depending on the concrete mediator. Colleagues should hold the ControlTower interface, not BengaluruTower. Then you can swap in a test double (a fake used in tests).

Interview questions

"What problem does the Mediator pattern solve?"

It removes many-to-many references between objects. Instead of n objects each knowing n - 1 others, they all talk to one mediator, which holds the interaction rules.

"What is the difference between Mediator and Observer?"

Observer is one-way broadcasting: a subject notifies subscribers, and each one decides how to react. Mediator is two-way coordination: colleagues report to the mediator, and the mediator decides what the others should do.

"How is Mediator different from Facade?"

A facade gives clients a simpler entry point into a subsystem, and the subsystem classes do not know it exists. A mediator coordinates peers that know about it and call into it. Facade simplifies, Mediator coordinates.

"What is the biggest risk with Mediator?"

The mediator turning into a God class that holds every rule and some business logic too. Keep it to coordination only, and split it by feature when it grows.

"Give a real example of Mediator in frameworks you have used."

Spring MVC's DispatcherServlet coordinates handler mappings, handler adapters and view resolvers, which never call each other directly. Chat servers are another example, where clients send to the server instead of to each other.

"How does Mediator help with testing?"

A colleague depends on one interface, so you can test it with a fake mediator. You can also test the mediator's rules with two or three simple colleagues instead of building the whole web.

"How many references do you save with a mediator for 10 components?"

Fully connected, 10 components need 10 x 9 = 90 directed references. With a mediator each component holds one reference, to the mediator, so 10. The mediator also keeps its own references back to them.

Run both examples

From the repository root:

mkdir -p out
javac -d out src/DesignPatterns/BehaviouralPatterns/MediatorPattern/Before/Main.java
java -cp out DesignPatterns.BehaviouralPatterns.MediatorPattern.Before.Main

javac -d out src/DesignPatterns/BehaviouralPatterns/MediatorPattern/After/Main.java
java -cp out DesignPatterns.BehaviouralPatterns.MediatorPattern.After.Main

In the Before output, AI-803 needs Main to request landing again. In the After output, the mediator remembers the queue and starts the handoff itself.

In this topic

Done with this topic?

How well do you know it?

PreviousMemento Pattern — Short Notes
Practise 7 questions