The Mediator Design Pattern is one of the important and widely used behavioral design patterns that centralizes communication between objects through a mediator object. Instead of objects talking directly to each other, they send messages via the mediator, reducing dependencies. This makes the system easier to manage and maintain.
- Centralizes communication between multiple objects
- Reduces direct dependencies between components
- Simplifies object interaction and maintenance
- Makes it easier to modify or add new components without affecting others
Components
1. Mediator: The Mediator interface defines the communication contract, specifying methods that concrete mediators should implement to facilitate interactions among colleagues.. It encapsulates the logic for coordinating and managing the interactions between these objects, promoting loose coupling and centralizing control over their communication.
2. Colleague: Colleague classes are the components or objects that interact with each other. They communicate through the Mediator, and each colleague class is only aware of the mediator, not the other colleagues. This isolation ensures that changes in one colleague do not directly affect others.
3. Concrete Mediator: Concrete Mediator is a specific implementation of the Mediator interface. It coordinates the communication between concrete colleague objects, handling their interactions and ensuring a well-organized collaboration while keeping them decoupled.
4. Concrete colleague: Concrete Colleague classes are the specific implementations of the Colleague interface. They rely on the Mediator to communicate with other colleagues, avoiding direct dependencies and promoting a more flexible and maintainable system architecture.
Uses
The Mediator pattern is commonly used to manage complex interactions between objects.
- GUI systems where buttons, text fields, and menus interact
- Chat applications where users communicate through a central server
- Air traffic control systems managing communication between airplanes
- Workflow or event-driven systems to coordinate multiple components
Working
The pattern works by introducing a mediator object that handles all communication between components.
- Colleague objects do not communicate directly with each other
- They send messages or requests to the mediator
- The mediator decides how to route or handle the communication
- This keeps objects loosely coupled and easier to manage
Communication flow between components

Below is the communication flow between components:
- A Concrete Colleague object sends a message or notification to the Concrete Mediator when it needs to communicate with another colleague.
- The Concrete Mediator receives the message and determines how to coordinate the interaction between the specific Concrete Colleague objects involved.
- The Concrete Mediator may then invoke methods on the Concrete Colleague objects to facilitate their communication.
- Colleague objects interact indirectly through the Concrete Mediator, maintaining loose coupling and avoiding direct dependencies.
Example
Problem Statement:
Several airplanes in an airport must coordinate their movements and communicate with one another in order to prevent collisions and guarantee safe takeoffs and landings. Direct communication between aircraft without a centralized mechanism could result in chaos and higher risk.
Challenges while implementing this system
- Air Traffic Complexity: Direct communication between airplanes might result in complex and error-prone coordination, especially when dealing with multiple aircraft in the same airspace.
- Collision Risks: Without a centralized control mechanism, the risk of collisions between airplanes during takeoffs, landings, or mid-flight maneuvers increases.
How Mediator Pattern help to solve above challenges?
By managing the complex coordination and communication between aircraft and air traffic controllers, the mediator pattern contributes to a safer and better-organized aviation system.
- Centralized Control: By serving as a mediator, the air traffic control tower helps aircraft communicate with one another. This guarantees that every aircraft is aware of the location and intentions of every other aircraft.
- Collision Avoidance: The mediator (air traffic control tower) manages the flow of airplanes, preventing collisions by providing clear instructions and coordinating their movements.

Implementation of above Example
Let’s break down into the component wise code
1. Colleague Interface(Airplane)
/* Colleague Interface */
#include <string>
#include <vector>
class Airplane {
public:
virtual void requestTakeoff() = 0;
virtual void requestLanding() = 0;
virtual void notifyAirTrafficControl(const std::string& message) = 0;
};
// Colleague Interface
public interface Airplane {
void requestTakeoff();
void requestLanding();
void notifyAirTrafficControl(String message);
}
# Colleague Interface
from abc import ABC, abstractmethod
class Airplane(ABC):
@abstractmethod
def requestTakeoff(self):
pass
@abstractmethod
def requestLanding(self):
pass
@abstractmethod
def notifyAirTrafficControl(self, message: str):
pass
// Colleague Interface
class Airplane {
requestTakeoff() {
throw new Error('Method not implemented.');
}
requestLanding() {
throw new Error('Method not implemented.');
}
notifyAirTrafficControl(message) {
throw new Error('Method not implemented.');
}
}
2. ConcreteColleague Class(CommercialAirplane)
// Concrete Colleague
#include <iostream>
#include "AirTrafficControlTower.h"
class CommercialAirplane {
private:
AirTrafficControlTower* mediator;
public:
CommercialAirplane(AirTrafficControlTower* mediator) {
this->mediator = mediator;
}
void requestTakeoff() {
mediator->requestTakeoff(this);
}
void requestLanding() {
mediator->requestLanding(this);
}
void notifyAirTrafficControl(const std::string& message) {
std::cout << "Commercial Airplane: " << message << std::endl;
}
};
// Concrete Colleague
public class CommercialAirplane implements Airplane {
private AirTrafficControlTower mediator;
public CommercialAirplane(AirTrafficControlTower mediator) {
this.mediator = mediator;
}
@Override
public void requestTakeoff() {
mediator.requestTakeoff(this);
}
@Override
public void requestLanding() {
mediator.requestLanding(this);
}
@Override
public void notifyAirTrafficControl(String message) {
System.out.println("Commercial Airplane: " + message);
}
}
# Concrete Colleague
class CommercialAirplane:
def __init__(self, mediator):
self.mediator = mediator
def request_takeoff(self):
self.mediator.request_takeoff(self)
def request_landing(self):
self.mediator.request_landing(self)
def notify_air_traffic_control(self, message):
print(f'Commercial Airplane: {message}')
// Concrete Colleague
class CommercialAirplane {
constructor(mediator) {
this.mediator = mediator;
}
requestTakeoff() {
this.mediator.requestTakeoff(this);
}
requestLanding() {
this.mediator.requestLanding(this);
}
notifyAirTrafficControl(message) {
console.log(`Commercial Airplane: ${message}`);
}
}
3. Mediator Interface(AirTrafficControlTower)
// Mediator Interface
#include <iostream>
#include <string>
#include <vector>
class Airplane {
public:
std::string name;
Airplane(std::string name) : name(name) {}
};
class AirTrafficControlTower {
public:
virtual void requestTakeoff(Airplane* airplane) = 0;
virtual void requestLanding(Airplane* airplane) = 0;
};
// Mediator Interface
public interface AirTrafficControlTower {
void requestTakeoff(Airplane airplane);
void requestLanding(Airplane airplane);
}
# Mediator Interface
from abc import ABC, abstractmethod
class Airplane:
def __init__(self, name):
self.name = name
class AirTrafficControlTower(ABC):
@abstractmethod
def requestTakeoff(self, airplane):
pass
@abstractmethod
def requestLanding(self, airplane):
pass
// Mediator Interface
class Airplane {
constructor(name) {
this.name = name;
}
}
class AirTrafficControlTower {
requestTakeoff(airplane) {}
requestLanding(airplane) {}
}
4. ConcreteMediator Class(AirportControlTower)
// Concrete Mediator
#include <iostream>
#include <string>
class AirTrafficControlTower {
public:
virtual void requestTakeoff(Airplane* airplane) = 0;
virtual void requestLanding(Airplane* airplane) = 0;
};
class AirportControlTower : public AirTrafficControlTower {
public:
void requestTakeoff(Airplane* airplane) override {
// Logic for coordinating takeoff
airplane->notifyAirTrafficControl("Requesting takeoff clearance.");
}
void requestLanding(Airplane* airplane) override {
// Logic for coordinating landing
airplane->notifyAirTrafficControl("Requesting landing clearance.");
}
};
class Airplane {
public:
void notifyAirTrafficControl(const std::string& message) {
std::cout << message << std::endl;
}
};
// Concrete Mediator
public class AirportControlTower implements AirTrafficControlTower {
@Override
public void requestTakeoff(Airplane airplane) {
// Logic for coordinating takeoff
airplane.notifyAirTrafficControl("Requesting takeoff clearance.");
}
@Override
public void requestLanding(Airplane airplane) {
// Logic for coordinating landing
airplane.notifyAirTrafficControl("Requesting landing clearance.");
}
}
"""
Concrete Mediator
"""
from abc import ABC, abstractmethod
class AirTrafficControlTower(ABC):
@abstractmethod
def requestTakeoff(self, airplane):
pass
@abstractmethod
def requestLanding(self, airplane):
pass
class AirportControlTower(AirTrafficControlTower):
def requestTakeoff(self, airplane):
# Logic for coordinating takeoff
airplane.notifyAirTrafficControl('Requesting takeoff clearance.')
def requestLanding(self, airplane):
# Logic for coordinating landing
airplane.notifyAirTrafficControl('Requesting landing clearance.')
class Airplane:
def notifyAirTrafficControl(self, message):
print(message)
"use strict";
// Concrete Mediator
class AirTrafficControlTower {
requestTakeoff(airplane) {
throw new Error('Method not implemented.');
}
requestLanding(airplane) {
throw new Error('Method not implemented.');
}
}
class AirportControlTower extends AirTrafficControlTower {
requestTakeoff(airplane) {
// Logic for coordinating takeoff
airplane.notifyAirTrafficControl('Requesting takeoff clearance.');
}
requestLanding(airplane) {
// Logic for coordinating landing
airplane.notifyAirTrafficControl('Requesting landing clearance.');
}
}
class Airplane {
notifyAirTrafficControl(message) {
console.log(message);
}
}
Complete code for the above example
Below is the complete code for the above example:
// Colleague Interface
#include <iostream>
#include <string>
using namespace std;
class Airplane {
public:
virtual void requestTakeoff() = 0;
virtual void requestLanding() = 0;
virtual void notifyAirTrafficControl(string message) = 0;
};
// Concrete Colleague
class CommercialAirplane : public Airplane {
private:
class AirTrafficControlTower* mediator;
public:
CommercialAirplane(AirTrafficControlTower* mediator) : mediator(mediator) {}
void requestTakeoff() override {
mediator->requestTakeoff(this);
}
void requestLanding() override {
mediator->requestLanding(this);
}
void notifyAirTrafficControl(string message) override {
cout << "Commercial Airplane: " << message << endl;
}
};
// Mediator Interface
class AirTrafficControlTower {
public:
virtual void requestTakeoff(Airplane* airplane) = 0;
virtual void requestLanding(Airplane* airplane) = 0;
};
// Concrete Mediator
class AirportControlTower : public AirTrafficControlTower {
public:
void requestTakeoff(Airplane* airplane) override {
// Logic for coordinating takeoff
airplane->notifyAirTrafficControl("Requesting takeoff clearance.");
}
void requestLanding(Airplane* airplane) override {
// Logic for coordinating landing
airplane->notifyAirTrafficControl("Requesting landing clearance.");
}
};
// Main function
int main() {
// Instantiate the Mediator (Airport Control Tower)
AirTrafficControlTower* controlTower = new AirportControlTower();
// Instantiate Concrete Colleagues (Commercial Airplanes)
Airplane* airplane1 = new CommercialAirplane(controlTower);
Airplane* airplane2 = new CommercialAirplane(controlTower);
// Set up the association between Concrete Colleagues and the Mediator
airplane1->requestTakeoff();
airplane2->requestLanding();
// Output:
// Commercial Airplane: Requesting takeoff clearance.
// Commercial Airplane: Requesting landing clearance.
delete airplane1;
delete airplane2;
delete controlTower;
return 0;
}
// Colleague Interface
interface Airplane {
void requestTakeoff();
void requestLanding();
void notifyAirTrafficControl(String message);
}
// Concrete Colleague
class CommercialAirplane implements Airplane {
private AirTrafficControlTower mediator;
public CommercialAirplane(AirTrafficControlTower mediator) {
this.mediator = mediator;
}
@Override
public void requestTakeoff() {
mediator.requestTakeoff(this);
}
@Override
public void requestLanding() {
mediator.requestLanding(this);
}
@Override
public void notifyAirTrafficControl(String message) {
System.out.println("Commercial Airplane: " + message);
}
}
// Mediator Interface
interface AirTrafficControlTower {
void requestTakeoff(Airplane airplane);
void requestLanding(Airplane airplane);
}
// Concrete Mediator
class AirportControlTower implements AirTrafficControlTower {
@Override
public void requestTakeoff(Airplane airplane) {
// Logic for coordinating takeoff
airplane.notifyAirTrafficControl("Requesting takeoff clearance.");
}
@Override
public void requestLanding(Airplane airplane) {
// Logic for coordinating landing
airplane.notifyAirTrafficControl("Requesting landing clearance.");
}
}
// Main class
public class MediatorAirplaneExample {
public static void main(String[] args) {
// Instantiate the Mediator (Airport Control Tower)
AirTrafficControlTower controlTower = new AirportControlTower();
// Instantiate Concrete Colleagues (Commercial Airplanes)
Airplane airplane1 = new CommercialAirplane(controlTower);
Airplane airplane2 = new CommercialAirplane(controlTower);
// Set up the association between Concrete Colleagues and the Mediator
airplane1.requestTakeoff();
airplane2.requestLanding();
// Output:
// Commercial Airplane: Requesting takeoff clearance.
// Commercial Airplane: Requesting landing clearance.
}
}
# Colleague Interface
from abc import ABC, abstractmethod
class Airplane(ABC):
@abstractmethod
def requestTakeoff(self):
pass
@abstractmethod
def requestLanding(self):
pass
@abstractmethod
def notifyAirTrafficControl(self, message):
pass
# Concrete Colleague
class CommercialAirplane(Airplane):
def __init__(self, mediator):
self.mediator = mediator
def requestTakeoff(self):
self.mediator.requestTakeoff(self)
def requestLanding(self):
self.mediator.requestLanding(self)
def notifyAirTrafficControl(self, message):
print("Commercial Airplane: " + message)
# Mediator Interface
class AirTrafficControlTower(ABC):
@abstractmethod
def requestTakeoff(self, airplane):
pass
@abstractmethod
def requestLanding(self, airplane):
pass
# Concrete Mediator
class AirportControlTower(AirTrafficControlTower):
def requestTakeoff(self, airplane):
# Logic for coordinating takeoff
airplane.notifyAirTrafficControl("Requesting takeoff clearance.")
def requestLanding(self, airplane):
# Logic for coordinating landing
airplane.notifyAirTrafficControl("Requesting landing clearance.")
# Main function
if __name__ == "__main__":
# Instantiate the Mediator (Airport Control Tower)
controlTower = AirportControlTower()
# Instantiate Concrete Colleagues (Commercial Airplanes)
airplane1 = CommercialAirplane(controlTower)
airplane2 = CommercialAirplane(controlTower)
# Set up the association between Concrete Colleagues and the Mediator
airplane1.requestTakeoff()
airplane2.requestLanding()
# Output:
# Commercial Airplane: Requesting takeoff clearance.
# Commercial Airplane: Requesting landing clearance.
// Colleague Interface
class Airplane {
requestTakeoff() {}
requestLanding() {}
notifyAirTrafficControl(message) {}
}
// Concrete Colleague
class CommercialAirplane extends Airplane {
constructor(mediator) {
super();
this.mediator = mediator;
}
requestTakeoff() {
this.mediator.requestTakeoff(this);
}
requestLanding() {
this.mediator.requestLanding(this);
}
notifyAirTrafficControl(message) {
console.log(`Commercial Airplane: ${message}`);
}
}
// Mediator Interface
class AirTrafficControlTower {
requestTakeoff(airplane) {}
requestLanding(airplane) {}
}
// Concrete Mediator
class AirportControlTower extends AirTrafficControlTower {
requestTakeoff(airplane) {
// Logic for coordinating takeoff
airplane.notifyAirTrafficControl("Requesting takeoff clearance.");
}
requestLanding(airplane) {
// Logic for coordinating landing
airplane.notifyAirTrafficControl("Requesting landing clearance.");
}
}
// Main function
(() => {
// Instantiate the Mediator (Airport Control Tower)
const controlTower = new AirportControlTower();
// Instantiate Concrete Colleagues (Commercial Airplanes)
const airplane1 = new CommercialAirplane(controlTower);
const airplane2 = new CommercialAirplane(controlTower);
// Set up the association between Concrete Colleagues and the Mediator
airplane1.requestTakeoff();
airplane2.requestLanding();
// Output:
// Commercial Airplane: Requesting takeoff clearance.
// Commercial Airplane: Requesting landing clearance.
})();
Output
Commercial Airplane: Requesting takeoff clearance. Commercial Airplane: Requesting landing clearance.
Real-Life Example
Let's imagine a group project in a classroom:
- Colleagues (Students): Each student in the class is like a colleague. They have their tasks but need to work together on a project.
- Mediator (Teacher): The teacher is like the mediator. Instead of students talking directly to each other, they talk to the teacher.
- Communication Flow: If a student needs information from another, they inform the teacher instead of contacting the other student directly. The teacher gathers the required information from the appropriate student and relays it back to the requester. In this way, students communicate indirectly through the teacher, which keeps communication organized and prevents chaos in the classroom.
Student talks to Teacher, Teacher manages the communication, and the information goes back through the Teacher to the requesting student. This way, everyone collaborates effectively, and individual students don't have to directly deal with all the details of each other's work.
Advantages
This pattern improves maintainability and reduces tight coupling.
- Reduces dependencies between interacting objects.
- Simplifies communication and control logic.
- Makes it easier to modify or add new components.
- Promotes cleaner and more organized code.
Disadvantages
Despite its benefits, the Mediator pattern has some drawbacks.
- Can become a bottleneck if the mediator grows too complex.
- Adds extra layer of abstraction.
- Difficult to maintain if many colleagues and interactions exist.