Last Updated: February 24, 2026
The Mediator Design Pattern is a behavioral pattern that defines an object (the Mediator) to encapsulate how a set of objects interact.
It promotes loose coupling by preventing objects from referring to each other directly, and lets you vary their interactions independently.
It’s particularly useful in situations where:
Let’s walk through a real-world example to see how we can apply the Mediator Pattern to build a more modular, loosely coupled system where components communicate cleanly and consistently.
Imagine you're building a login form with the following UI components:
The logic of the form is simple:
Sounds simple, right? Let’s try implementing this with each component talking directly to the others.
In a straightforward implementation, each component holds direct references to the components it needs to interact with. The text fields know about the button, and the button knows about the text fields and the label.
At first glance, this seems fine. But as soon as you add a few more components (e.g., a "remember me" checkbox, a "forgot password" link), the logic starts to spiral out of control.
Every component knows about others: the TextField knows the Button, the Button knows the TextField and the Label. A change in one component's logic often requires updates in others, creating a fragile system.
You cannot easily reuse these components elsewhere. They are hard-wired to interact with specific peers, making them context-dependent.
Adding or modifying interactions requires changing the logic of multiple classes. This violates the Open/Closed Principle and makes the system harder to test and evolve.
Each component contains not only its own logic but also coordinating behavior, making it harder to isolate responsibilities.
We need a way to:
This is exactly what the Mediator Pattern is designed to solve.
The Mediator Pattern promotes loose coupling by centralizing communication between objects. Instead of having components refer to and interact with each other directly, they communicate through a mediator.
Two characteristics of the pattern:
This leads to a cleaner separation of concerns and makes components easier to reuse in different contexts.
Think about an air traffic control tower. Planes approaching an airport do not communicate with each other to negotiate landing order, runway assignments, or holding patterns. That would be chaos, especially with dozens of planes in the air simultaneously. Instead, every pilot talks only to the control tower.
The tower knows the position, speed, and fuel status of every plane and coordinates them accordingly: "Flight 237, hold at 5,000 feet. Flight 412, you are cleared for runway 28L."
The tower is the mediator. Planes are the components. If a new plane enters the airspace, the tower handles it. If a plane diverts, the tower adjusts. The other planes never need to know.
Declares the interface for communication between components. Typically has a single method like componentChanged(), notify(), or send().
The mediator interface should be narrow. A single componentChanged(component) method is almost always sufficient. The mediator identifies the sender and decides what to do based on the sender's identity and state.
Implements the mediator interface. Contains all the coordination logic and holds references to every component it manages.
The concrete mediator is allowed to know about concrete component types. This is intentional. The mediator absorbs the coupling that would otherwise be spread across all components. One class knowing about everyone is better than everyone knowing about everyone.
Holds a reference to the mediator and provides a notifyMediator() convenience method.
These are the actual components (e.g., TextField, Button, Label) that perform actions and notify the mediator when changes occur. They never talk directly to each other.
Let us refactor the tightly coupled login form using the Mediator pattern. Each UI component will interact only with the mediator, which will handle all coordination and logic.
We will do this in five steps.
This interface defines how components will notify the mediator when their state changes. It provides a method like componentChanged() to centralize communication.
This abstract base class holds a reference to the mediator and provides a method to notify it when something changes. All UI elements will extend this class.
This ensures a consistent way for all components to communicate with the mediator.
Each component (TextField, Button, Label) extends UIComponent and defines its own local behavior. These components no longer interact with each other directly. They only notify the mediator.
This class knows about all components and defines the rules for how they should behave in response to one another. When a component changes, the mediator coordinates the appropriate actions.
Now, the client wires everything together. Components are instantiated, linked to the mediator, and can be used without knowing about each other.
TextField, Button, and Label can be reused in other contextsLet us work through a second example to reinforce the pattern. This time, we are building a simple chat room. Users send messages to the chat room, and the chat room broadcasts them to all other connected users. No user holds a direct reference to any other user.
ChatMediator declares the message-sending contract, and User is the abstract base that holds a reference to the mediator. ChatRoom is the concrete mediator that manages users and routes messages. ChatUser sends and receives messages without knowing about any other user.
Notice how no user knows about any other user. Alice calls send(), which delegates to the chat room. The chat room iterates through its user list and calls receive() on everyone except Alice. If we add a fourth user, we register them with the chat room. Alice, Bob, and Charlie are completely unaffected.
This example also illustrates the difference between Mediator and Observer. In Observer, the subject broadcasts identical data to all observers, and each observer decides what to do with it. Here, the mediator actively decides who gets the message (everyone except the sender) and what format the message takes. The mediator is not just broadcasting; it is coordinating.