Java design pattern: Mediator

Today we will look at another Java design pattern from the category of behavioral patterns – Mediator. Design patterns in this category deal with the communication (interaction) between objects and their responsibility.

What is the Mediator design pattern?

The Mediator design pattern is used to simplify communication between objects in a system by providing a central point for communication between objects. The mediator plays the role of an intermediary and ensures that objects do not communicate directly, which keeps the system easily extensible and maintainable.

What problem does the Mediator design pattern solve?

The issue it tackles is that in complex systems, communication between objects can become complicated and unclear. With the number of classes or objects, the complexity of interrelations increases The aim of this pattern is to ensure that objects do not know each other and thus do not depend on each other and that communication between objects does not take place directly, but through a single intermediary (mediator). This minimizes object binding to each other and makes it easier to change or add new relationships, since all communications are through an intermediary.

Example of Mediator implementation in Java

We will now demonstrate how the Mediator design pattern can simplify communication between objects and remove unnecessary dependencies between them by programming a simple chat room that allows communication between participants in a discussion via both public and private messages.

Mediator.java

package designpatterns;

public interface Mediator {
    void poslatSpravu(Diskuter od, String sprava);
    void poslatSukromnuSpravu(Diskuter odkoho, Diskuter komu, String sprava);
}

The Mediator interface defines methods for sending messages to all participants in a discussion and for sending private messages to a specific participant.

Chat.java

package designpatterns;

import java.util.ArrayList;
import java.util.List;

public class Chat implements Mediator {
    private List<Diskuter> diskutujuci;

    public Chat() {
        this.diskutujuci = new ArrayList<>();
    }

    public void pridat(Diskuter diskuter) {
        diskutujuci.add(diskuter);
    }

    @Override
    public void poslatSpravu(Diskuter od, String sprava) {
        for(Diskuter prijmatel : diskutujuci) {
            // Poslanie správy všetkým okrem odosielateľa.
            if(prijmatel != od) {
                prijmatel.prijatSpravu(sprava);
            }
        }
    }

    @Override
    public void poslatSukromnuSpravu(Diskuter od, Diskuter komu, String sprava) {
        for(Diskuter prijmatel : diskutujuci) {
            // Poslanie správy konkrétnemu príjmateľovi.
            if(prijmatel == komu) {
                prijmatel.prijatSukromnuSpravu(od, sprava);
            }
        }
    }
}

The Chat class provides an implementation of the Mediator interface. It contains a list of discussants and ensures that messages are sent either to all participants or to specific people.

Diskuter.java

package designpatterns;

public interface Diskuter {
    void poslatSpravu(String sprava);
    void prijatSpravu(String sprava);
    void poslatSukromnuSpravu(Diskuter komu, String sprava);
    void prijatSukromnuSpravu(Diskuter odkoho, String sprava);
}

The Diskuter interface defines methods for sending and receiving public and private messages.

Clen.java

package designpatterns;

public class Clen implements Diskuter {
    private String meno;
    private Chat chat;

    public Clen(String meno, Chat chat) {
        this.meno = meno;
        this.chat = chat;
        chat.pridat(this);
    }

    @Override
    public void poslatSpravu(String sprava) {
        System.out.println(meno + " posiela správu: " + sprava);
        chat.poslatSpravu(this, sprava);
    }

    @Override
    public void prijatSpravu(String sprava) {
        System.out.println(meno + " prijal/a správu: " + sprava);
    }

    @Override
    public void poslatSukromnuSpravu(Diskuter komu, String sprava) {
        System.out.println(meno + " posiela súkromnú správu: " + sprava);
        chat.poslatSukromnuSpravu(this, komu, sprava);
    }

    @Override
    public void prijatSukromnuSpravu(Diskuter odkoho, String sprava) {
        System.out.println(meno + " prijal/a súkromnú správu: " + sprava);
    }
}

The Clen (member) class implements the Diskuter interface. Each member has a name and a chat to which they are added. It can send messages to everyone, receive messages and send private messages.

Main.java

import designpatterns.Chat;
import designpatterns.Clen;
import designpatterns.Diskuter;

public class Main {
    public static void main(String[] args) {
        Chat chat = new Chat();
        Diskuter clen1 = new Clen("Jozef", chat);
        Diskuter clen2 = new Clen("Petra", chat);
        Diskuter clen3 = new Clen("Dominik", chat);
        Diskuter clen4 = new Clen("Karolina", chat);
        clen1.poslatSpravu("Ahoj všetci!");
        clen4.poslatSukromnuSpravu(clen1, "Ahoj Jozef!");
        clen3.poslatSpravu("Idete si zahrať stolný futbal?");
        clen1.poslatSpravu("Jasné, prečo nie.");
        clen2.poslatSpravu("Mám prácu, ale jednu si zahrám.");
        clen4.poslatSpravu("Ja sa pridám.");
        clen3.poslatSpravu("Za minútku dole.");
        clen2.poslatSukromnuSpravu(clen1, "Vyklepeme ich ako rezne :-D");
    }
}

The Main class creates a chat object and adds a few chat members to it. It then demonstrates the functionality of chat – the communication between members, such as sending and receiving messages, including private messages.

There are no fixed links between the objects (members of the discussion), all communication takes place through an intermediary – the chat. Adding new members to the discussion is just as easy, and it doesn’t increase the complexity of the communication.

The output of this example is:

There are no fixed links between the objects (members of the discussion), all communication takes place through an intermediary - the chat.

Summary

The Mediator design pattern is often used when we want to achieve simplification in communication and messaging between objects through centralized communication. The complexity of a system increases with the rise of dependencies and relationships between objects; this design pattern helps significantly reduce them.

We have prepared the files with the above example in the form of code that you can run directly in Java. Download the Java Mediator code here.

If you’re a Java developer looking for work, check out our employee benefits and respond to our job offers.

About the author

Jozef Wagner

Java Developer Senior

Viac ako 10 rokov programujem v Jave, momentálne pracujem v msg life Slovakia ako Java programátor senior a pomáham zákazníkom implementovať ich požiadavky do poistného softvéru Life Factory. Vo voľnom čase si rád oddýchnem v lese, prípadne si zahrám nejakú dobrú počítačovú hru.

Let us know about you