Mediator Design Patter in Java

Reading Time: 4 minutes

Definition

The Mediator Pattern falls into the Behavioral Pattern. In simple terms, there is centrally a mediator that handles communication between object in a loosely coupled way, thus objects shall not talk to each other directly. Furthermore, often developers get confused with the Observer pattern, and they seem pretty similar. However, we can break the ultimate difference down like this:

  • Observer Pattern: The objects are not interested in each other, so the relationship is one-to-many, many objects are interested in the state change of one object,
  • Mediator Pattern: The objects are interested to interact with many other objects, so the relation is many to many.

To better understand the deal in the Mediator pattern please study the below illustration;

Before The Mediator Pattern Applied

After The Mediator Pattern Applied

Rules of the Pattern

In this pattern there are two components that we need to create and mind;

Colleagues: These objects are primarily the targets that will not talk to each other directly and have the same base type abstract class or interface that will inherit the same attributes. Furthermore, they will have have the knowledge of the mediator component, which means that each of them will have access an instance to the mediator pattern, rather than having instances to other colleague objects.

Mediator: The centralized component that manages the communication between colleague components.

Example Code Snippet

To better understand the concept, I have developed a simple HR Organization suite. Here the HR is the mediator that knows all the participant Organization units and handles the communication between the Organization components. Then last of all we have the Organization base type that has all the common attributes, Manager and Employee objects are the child classes for the organization, they are separated and have their own functions. The communication is eliminated.

You will see some actions;

  • Registration: A new organization type is created, then it is instantly registered in the HR list,
  • Announcement: HR makes the announcement to all the whole organization regardless of the Organization instance is Manager or Employee,
  • Initiation of the Resignation: Here when an employee resigns, the employee will not talk to the Manager directly, but HR that initiates the process and talks to the Manager,
  • Surprise Party Preparation: After the resignation process is approved by the manager, the HR throws a surprise party without notifying the resigning employee and makes an announcement to the whole Organization.

HR.java

public interface HR {
    void registerOrganization(Organization organization);
    void makeAnnouncementToOrganization(final String message);
    void initiateResignationProcess(Organization employee, Organization manager);
}

HRImplementation.java

import java.util.HashSet;
import java.util.Set;

public class HRImplementation implements HR {
    private final Set<Organization> listOfOrganization = new HashSet<Organization>();

    @Override
    public void registerOrganization(Organization organization) {
        listOfOrganization.add(organization);
    }

    @Override
    public void makeAnnouncementToOrganization(String message) {
        System.out.println("Making announcement to the whole organization");
        for (Organization organization : listOfOrganization) {
            organization.receiveAnnouncement(message);
        }
    }

    @Override
    public void initiateResignationProcess(Organization employee, Organization manager) {
        System.out.println("Employee " + employee.getName() + " would like to resign from the company");
        System.out.println("HR is notifying the manager");
        boolean managerResponse = ((Manager) manager).decideAndFinalizeResignation(employee);
        if (managerResponse) {
            System.out.println(manager.getName() + " has approved " + employee.getName() + "\'s resignation") ;
            prepareSurpriseParty(employee);
        }
    }

    private void prepareSurpriseParty(Organization resigningEmployee) {
        System.out.println("Preparing the surprise party for " + resigningEmployee.getName());
        for (Organization organization : listOfOrganization) {
            if (organization != resigningEmployee)
                organization.receiveAnnouncement("Guys " + resigningEmployee.getName() + " is resigning his position, and you " + organization.getName() + " are invited to his surprise party");
        }
    }
}

Organization.java

public abstract class Organization {
    private final HR hr;
    private final String name;

    public Organization(HR hr, String name) {
        this.hr = hr;
        this.name = name;
        this.hr.registerOrganization(this);
    }

    public void receiveAnnouncement(final String message) {
        System.out.println(this.getClass().getSimpleName() + " " + name + " received the announcement " + message);
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Organization that = (Organization) o;

        return name.equals(that.name);
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}

Manager.java

public class Manager extends Organization {
    private HR hr;
    private String managerName;

    public Manager(HR hr, String name) {
        super(hr, name);
        this.hr = hr;
        this.managerName = name;
    }

    public boolean decideAndFinalizeResignation(Organization employee) {
        System.out.println("Manager " + managerName + " is considering " + employee.getName() + "\'s resignation");
        return true;
    }
}

Employee.java

public class Employee extends Organization {
    private HR hr;
    private String employeeName;

    public Employee(HR hr, String name) {
        super(hr, name);
        this.hr = hr;
        this.employeeName = name;
    }

    public void giveResignation(Organization manager){
        System.out.println("Employee " + employeeName + " would like to resign");
        hr.initiateResignationProcess(this, manager);
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        HR hr = new HRImplementation();
        Organization konrad = new Manager(hr, "Konrad");
        Organization tugrul = new Employee(hr, "Tugrul");
        Organization oguz = new Employee(hr, "Oguz");
        Organization altan = new Employee(hr, "Altan");

        hr.makeAnnouncementToOrganization("Welcome guys :)");
        ((Employee) tugrul).giveResignation(konrad);
    }
}

Console Output

Making announcement to the whole organization
Manager Konrad received the announcement Welcome guys 🙂
Employee Altan received the announcement Welcome guys 🙂
Employee Oguz received the announcement Welcome guys 🙂
Employee Tugrul received the announcement Welcome guys 🙂
Employee Tugrul would like to resign
Employee Tugrul would like to resign from the company
HR is notifying the manager
Manager Konrad is considering Tugrul’s resignation
Konrad has approved Tugrul’s resignation
Preparing the surprise party for Tugrul
Manager Konrad received the announcement Guys Tugrul is resigning his position, and you Konrad are invited to his surprise party
Employee Altan received the announcement Guys Tugrul is resigning his position, and you Altan are invited to his surprise party
Employee Oguz received the announcement Guys Tugrul is resigning his position, and you Oguz are invited to his surprise party

In Contemporary Examples

  • java.util.Timer class schedule methods,
  • Java Executor executor method,
  • java.lang.reflect.Method invoke method,
  • JMS and Message Brokers heavily utilizes this pattern along with the Observer Pattern,
  • Spring’s MVC Pattern makes use in the Dispatcher Servlet where mediator handles all the web requests as well as the controller objects.