Open In App

Mediator Design Pattern

Last Updated : 18 Dec, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

The Mediator Design Pattern simplifies communication between multiple objects in a system by centralizing their interactions through a mediator. Instead of objects interacting directly, they communicate via a mediator, reducing dependencies and making the system easier to manage.
Mediator-Design-Pattern

What is the Mediator Design Pattern?

A mediator design pattern is one of the important and widely used behavioral design patterns. Mediator enables the decoupling of objects by introducing a layer in between so that the interaction between objects happens via the layer. Real Life

  • If the objects interact with each other directly, the system components are tightly coupled with each other making higher maintainability cost and not hard to extend.
  • The mediator pattern focuses on providing a mediator between objects for communication and helps in implementing loose coupling between objects.

It defines how a mediator object facilitates the interaction between other objects, guiding their behavior and communication without them being directly aware of each other. This pattern emphasizes the behavior and communication patterns among objects.

Real-Life Analogy of the Mediator Design Pattern

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 tell the teacher.
    • The teacher figures out how to get the needed information from the other students.
    • The teacher then relays the information back to the requesting student.
    • Students communicate indirectly through the teacher, keeping things organized and preventing 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.

Components of the Mediator Design Pattern

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.

How components are interacting with each other ?

MediatorPatternClassDiagram

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.

Mediator Design Pattern example(with implementation)

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.

What can be the 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.
MediatorDesignPatternExample

Below is the code of above problem statement using Command Pattern:

1. Colleague Interface(Airplane)

Java
// Colleague Interface
public interface Airplane {
    void requestTakeoff();
    void requestLanding();
    void notifyAirTrafficControl(String message);
}

2. ConcreteColleague Class(CommercialAirplane)

Java
// 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);
    }
}

3. Mediator Interface(AirTrafficControlTower)

Java
// Mediator Interface
public interface AirTrafficControlTower {
    void requestTakeoff(Airplane airplane);
    void requestLanding(Airplane airplane);
}

4. ConcreteMediator Class(AirportControlTower)

Java
// 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.");
    }
}

Complete code for the above example

Below is the complete code for the above example:

Java
// 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.
    }
}
Output
Commercial Airplane: Requesting takeoff clearance.
Commercial Airplane: Requesting landing clearance.

When to use the Mediator Design Pattern?

  • Complex Communication: Your system involves a set of objects that need to communicate with each other in a complex manner, and you want to avoid direct dependencies between them.
  • Loose Coupling: You want to promote loose coupling between objects, allowing them to interact without knowing the details of each other's implementations.
  • Centralized Control: You need a centralized mechanism to coordinate and control the interactions between objects, ensuring a more organized and maintainable system.
  • Changes in Behavior: You anticipate changes in the behavior of components, and you want to encapsulate these changes within the mediator, preventing widespread modifications.
  • Enhanced Reusability: You want to reuse individual components in different contexts without altering their internal logic or communication patterns.

When not to use the Mediator Design Pattern?

  • Simple Interactions: The interactions between components are straightforward, and introducing a mediator would add unnecessary complexity.
  • Single Responsibility Principle (SRP): The Single Responsibility Principle states that each component has a single responsibility; adding a mediator could go against this principle and result in less maintainable code.
  • Performance Concerns: Introducing a mediator could introduce a performance overhead, especially in situations where direct communication between components is more efficient.
  • Small Scale Applications: In small-scale applications with a limited number of components, the overhead of implementing a mediator might outweigh its benefits.
  • Over-Engineering: If the Mediator pattern appears like an over-engineered answer for your system's particular requirements, don't use it. Always take into account the particular requirements of your application as well as the trade-offs.



Next Article
Practice Tags :

Similar Reads

  翻译: