• Shift Elevate
  • Posts
  • Mediator Pattern: Simplify Object Communication with Centralized Control

Mediator Pattern: Simplify Object Communication with Centralized Control

The Pain of Complex Object Interactions

Picture this: You're building an air traffic control system where multiple aircraft need to coordinate landings and takeoffs. Your initial approach seems logical: aircraft communicate directly with each other to avoid collisions.

But as the airport grows, you realize the chaos: each aircraft needs to know about every other aircraft, constantly checking positions, coordinating runway usage, and negotiating priorities. Adding a new aircraft means every existing aircraft's logic needs updating. It's a tangled web of dependencies where planes are tightly coupled to each other.

The Mediator pattern solves this complexity by introducing a control tower that centralizes all communication, promoting loose coupling and making the system easier to understand and maintain.

Understanding the Mediator Pattern

The Mediator pattern defines an object that encapsulates how a set of objects interact. Instead of objects referring to each other directly, they communicate through the mediator, which acts as a central hub for all interactions.

Think of it like an air traffic control tower: instead of pilots communicating directly with each other (which would be chaotic), they all communicate through the control tower, which coordinates and manages all interactions safely and efficiently.

This pattern promotes Loose Coupling, Centralized Control, and Simplified Communication while reducing the complexity of object interactions.

Without Mediator: Components communicate directly with each other, creating tight coupling. Each component needs to know about every other component, leading to complex dependencies and difficult maintenance.

With Mediator: Components communicate through a central mediator. The mediator coordinates all interactions, and components only need to know about the mediator, not each other.

Mediator Pattern Components

Core Components

Complete Java Implementation

Let's build an air traffic control system that demonstrates the Mediator pattern's power in preventing direct communication chaos.

Mediator Interface

public interface ControlTower {
    void requestLanding(Aircraft aircraft);
    void requestTakeoff(Aircraft aircraft);
    void reportPosition(Aircraft aircraft, String position);
    void registerAircraft(Aircraft aircraft);
    void notifyGroundControl(GroundControl groundControl);
}

Concrete Mediator

public class AirTrafficControlTower implements ControlTower {
    private List<Aircraft> aircrafts = new ArrayList<>();
    private GroundControl groundControl;
    private boolean runwayAvailable = true;

    @Override
    public void registerAircraft(Aircraft aircraft) {
        aircrafts.add(aircraft);
    }

    @Override
    public void notifyGroundControl(GroundControl groundControl) {
        this.groundControl = groundControl;
    }

    @Override
    public void requestLanding(Aircraft aircraft) {
        if (runwayAvailable) {
            runwayAvailable = false;
            System.out.println("Tower: " + aircraft.getName() + " cleared for landing");

            // Notify other aircraft to hold
            for (Aircraft other : aircrafts) {
                if (other != aircraft) {
                    other.receiveMessage("Hold position, " + aircraft.getName() + " is landing");
                }
            }

            // Notify ground control
            if (groundControl != null) {
                groundControl.receiveNotification(aircraft.getName() + " is landing");
            }
        } else {
            aircraft.receiveMessage("Runway occupied, please hold");
        }
    }

    @Override
    public void requestTakeoff(Aircraft aircraft) {
        if (runwayAvailable) {
            runwayAvailable = false;
            System.out.println("Tower: " + aircraft.getName() + " cleared for takeoff");
        } else {
            aircraft.receiveMessage("Runway occupied, hold for takeoff");
        }
    }

    @Override
    public void reportPosition(Aircraft aircraft, String position) {
        System.out.println("Tower: " + aircraft.getName() + " reported at " + position);
        runwayAvailable = true;

        // Notify ground control about aircraft position
        if (groundControl != null) {
            groundControl.receiveNotification(aircraft.getName() + " at " + position);
        }
    }
}

Aircraft Component

public class Aircraft {
    private String name;
    private ControlTower tower;

    public Aircraft(String name, ControlTower tower) {
        this.name = name;
        this.tower = tower;
        tower.registerAircraft(this);
    }

    public void requestLanding() {
        System.out.println(name + ": Requesting landing clearance");
        tower.requestLanding(this);
    }

    public void requestTakeoff() {
        System.out.println(name + ": Requesting takeoff clearance");
        tower.requestTakeoff(this);
    }

    public void reportPosition(String position) {
        System.out.println(name + ": Reporting position - " + position);
        tower.reportPosition(this, position);
    }

    public void receiveMessage(String message) {
        System.out.println(name + " received: " + message);
    }

    public String getName() {
        return name;
    }
}

Ground Control Component

public class GroundControl {
    private String name;

    public GroundControl(String name) {
        this.name = name;
    }

    public void receiveNotification(String message) {
        System.out.println(name + " notified: " + message);
    }
}

Client

public class AirTrafficControllerDemo {
    public static void main(String[] args) {
        // Create control tower (mediator)
        ControlTower tower = new AirTrafficControlTower();

        // Create and set ground control
        GroundControl groundControl = new GroundControl("Ground Control");
        tower.notifyGroundControl(groundControl);

        // Create aircraft
        Aircraft flight1 = new Aircraft("Flight 101", tower);
        Aircraft flight2 = new Aircraft("Flight 202", tower);

        System.out.println("=== Air Traffic Control Demo ===\n");

        // Flight 1 requests landing
        flight1.requestLanding();

        System.out.println();

        // Flight 2 tries to land while runway is occupied
        flight2.requestLanding();

        System.out.println();

        // Flight 1 reports landed
        flight1.reportPosition("Gate A");

        System.out.println();

        // Now Flight 2 can land
        flight2.requestLanding();
    }
}

Expected Output:

=== Air Traffic Control Demo ===

Flight 101: Requesting landing clearance
Tower: Flight 101 cleared for landing
Flight 202 received: Hold position, Flight 101 is landing
Ground Control notified: Flight 101 is landing

Flight 202: Requesting landing clearance
Flight 202 received: Runway occupied, please hold

Flight 101: Reporting position - Gate A
Tower: Flight 101 reported at Gate A
Ground Control notified: Flight 101 at Gate A

Flight 202: Requesting landing clearance
Tower: Flight 202 cleared for landing
Flight 101 received: Hold position, Flight 202 is landing
Ground Control notified: Flight 202 is landing

🚀 Get the Complete Implementation

The full code with advanced mediator implementations and complex interaction scenarios is available in our Design Patterns Repository.

# Clone and run the complete demo
git clone https://github.com/shift-elevate/design-patterns.git
cd design-patterns
mvn test -Dtest=MediatorPatternTest

Real World Examples

The Mediator pattern is extensively used in real world applications:

1. GUI Frameworks

Modern GUI frameworks use the Mediator pattern extensively for component communication. Instead of UI components directly communicating with each other, they communicate through a central mediator that manages events, state changes, and component interactions.

2. Chat Applications

Chat applications use the Mediator pattern to manage communication between users. The chat server acts as a mediator, receiving messages from one user and distributing them to all other users in the chat room.

3. Workflow Management Systems

Business process management systems use the Mediator pattern to coordinate different workflow steps, ensuring that each step communicates through a central workflow engine rather than directly with other steps.

When to Use the Mediator Pattern

Understanding when to apply the Mediator pattern is crucial for making the right architectural decisions. Here's when it shines and when alternatives might be better:

Ideal Scenarios:

  • You have a set of objects that communicate in well defined but complex ways.

  • You want to avoid tight coupling between objects that interact.

  • You need to reuse objects in different contexts without changing their communication logic.

  • You want to centralize control over how objects interact.

Skip It When:

  • The communication between objects is simple and doesn't benefit from centralization.

  • You have a small number of objects with minimal interactions.

Next Steps: Apply Mediator Pattern in Your Project

Ready to implement the Mediator pattern in your own projects? Here's a structured approach to get you started:

  1. Identify Complex Interactions: Look for areas where multiple objects need to communicate with each other.

  2. Define Communication Protocol: Create a mediator interface that defines how objects should interact.

  3. Implement Central Mediator: Build a concrete mediator that handles all object interactions.

  4. Refactor Components: Modify existing objects to communicate through the mediator.

  5. Test Interaction Scenarios: Ensure all communication flows work correctly through the mediator.

The Mediator pattern transforms complex, tightly coupled object interactions into clean, maintainable systems. By centralizing communication through a mediator, you build systems that are easier to understand, modify, and extend.

Found this helpful? Share it with a colleague who's struggling with complex object interactions. Got questions? We'd love to hear from you at [email protected]