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
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
| Part | In our example | Job |
|---|---|---|
| Mediator | ControlTower | The interface (list of methods) colleagues call when something happens. |
| Concrete mediator | BengaluruTower | Holds the rules and the state (who is on the runway, who is waiting). |
| Colleague | Flight | Knows only the mediator. Reports events and follows instructions. |
| Client | Main | Creates the tower, then creates flights with a reference to it. |
One call, step by step
AI-803 is holding. 6E-512 leaves the runway.
How it fixes each problem
| Problem | With Mediator |
|---|---|
n x (n - 1) peer references | n flight-to-tower references. The tower keeps its own references to the active and queued flights |
| Runway rule copied into every flight | Lives in BengaluruTower only |
| Nobody owns the waiting order | The tower keeps a FIFO queue and hands out the runway |
| New flight means rewiring all flights | New flight just gets the tower in its constructor |
| Testing needs every flight | Test 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.
| Mediator | Observer | Facade | |
|---|---|---|---|
| Direction | Two 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 rules | The 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 example | Air traffic tower, chat room server | Swiggy order status pushing to app, SMS and the restaurant | A 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 coordinatesHandlerMapping,HandlerAdapterandViewResolverbeans. 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.TimerandExecutorService. 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
Flightwith 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
ControlTowerinterface, notBengaluruTower. 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
DispatcherServletcoordinates 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.MainIn 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.