Skip to content
FollowtheDamnCode

Mediator

Replace a tangle of objects talking to each other with one coordinator they all talk through.

Big idea

A Mediator centralises how a group of objects interact. Instead of every component holding references to every other and calling them directly, each one tells the mediator what happened, and the mediator decides who else needs to react. N objects with N × (N−1) connections become N objects each with one.

The problem it solves

A flight search form has a one-way/return toggle, a return-date picker, a passenger counter, a "travelling with infant" checkbox, and a Search button. Rules: the return date is enabled only for return trips; the infant box is enabled only when there's at least one adult; Search is enabled only when the form is complete. If each widget calls the others directly, the toggle knows the date picker and the button; the counter knows the checkbox and the button; and so on. No widget can be reused on another form, and the rules are smeared across five classes.

Think of it like

An airport control tower. Planes don't radio each other to negotiate who lands first — that would be dozens of conversations and a disaster waiting to happen. Each plane talks only to the tower; the tower sees everything and gives each plane its instructions.

Structure

Components know only the mediator

In code

A form whose widgets never reference each other
class Component:
    def __init__(self, mediator, name):
        self.mediator, self.name, self.enabled = mediator, name, True
    def changed(self):
        self.mediator.changed(self)               # "something happened to me"


class TripToggle(Component):
    def __init__(self, m):
        super().__init__(m, "trip"); self.value = "one-way"
    def set(self, v):
        self.value = v; self.changed()

class DatePicker(Component):
    def __init__(self, m, name):
        super().__init__(m, name); self.value = None
    def set(self, v):
        self.value = v; self.changed()

class Counter(Component):
    def __init__(self, m):
        super().__init__(m, "adults"); self.value = 0
    def set(self, v):
        self.value = v; self.changed()


class SearchForm:                                 # the mediator: every rule lives here
    def __init__(self):
        self.trip = TripToggle(self)
        self.depart = DatePicker(self, "depart")
        self.ret = DatePicker(self, "return")
        self.adults = Counter(self)
        self.search_enabled = False
        self.changed(None)

    def changed(self, component):
        self.ret.enabled = self.trip.value == "return"
        complete = self.depart.value and self.adults.value > 0 and (
            not self.ret.enabled or self.ret.value)
        self.search_enabled = bool(complete)

    def status(self):
        return f"return date {'on ' if self.ret.enabled else 'off'} | search {'ready' if self.search_enabled else 'blocked'}"


form = SearchForm()
print(form.status())
form.depart.set("2026-12-20"); form.adults.set(2)
print(form.status())
form.trip.set("return")
print(form.status())
form.ret.set("2026-12-27")
print(form.status())
output
return date off | search blocked
return date off | search ready
return date on  | search blocked
return date on  | search ready

Run and edit it in the app.

DatePicker and Counter are generic widgets — they'd work on any form. Only SearchForm knows this form's rules.

Six components all need to react to each other. Roughly how many direct links does a mediator replace?

Watch it

How to implement it

  1. Identify a group of classes that are tightly interconnected and hard to reuse.
  2. Define a mediator interface with a notification method (changed(sender, event)).
  3. Give each component a reference to the mediator and make it notify instead of calling peers.
  4. Move all the "when X changes, update Y" rules into the concrete mediator.

When to use it — and when not to

Use it for dialogs and forms, chat rooms (users send to the room, not to each other), workflow coordination between services, or game rooms where many objects interact. Watch for the mediator turning into a god object — if it grows unmanageable, split it by feature, or switch to Observer-style events where components don't need a central brain.

Pros and cons

ProsCons
Components become reusable and simpleThe mediator can grow into a god object
Interaction rules in one placeA single point of failure and of change
Fewer, clearer dependenciesCan hide which component affects which

How it relates

  • Facade simplifies a subsystem for outsiders who use it; a mediator coordinates insiders who know it.
  • Observer is often how components notify the mediator; the difference is intent — observer broadcasts to anyone, mediator routes deliberately.
  • Chain of Responsibility passes requests in a line; a mediator is a hub.
  • The Elevator system case study uses a dispatcher as the mediator between floors and cars.

What's the key difference between Mediator and Facade?

Key terms

  • Mediator — An object that encapsulates how a set of objects interact.
  • Colleague — A component that communicates through the mediator instead of directly with peers.
  • God object — A class that accumulates too much responsibility — the main risk for mediators.