Mediator Design Pattern in Java

This article explains Mediator design pattern in java with UML class diagram. It then takes an example scenario in java and explains it with class diagram and code.
Introduction Mediator Design Pattern is a behavioral design pattern among the Gang Of Four(GOF) Design PatternsClick to read: Gang Of Four(GOF) Design Patterns. Being a behavioral design pattern, the Mediator pattern deals with how the objects of the system under design interact with each other. What is Mediator Design Pattern In a Mediator Design Pattern implementation, the interaction between a set of objects is encapsulated in a separate object, called the mediator. The objects, called colleagues, no longer refer to each other directly; when one of them needs to communicate, it talks to the mediator, which decides which other objects to involve. This promotes loose coupling: each colleague depends only on the mediator, so colleagues can be changed, added or reused independently, and the logic of how they cooperate lives in one place. Scenarios in which Mediator Design Pattern can be used
  1. Object-to-object communications are complex: When many objects communicate with many others, the number of connections grows to N x N for N objects. A mediator reduces it to N connections - each object to the mediator - and encapsulates the complexity in the mediator.
  2. Object reuse is limited because of complex communications with other objects: When objects are hard to reuse because they refer to many others. Moving the communication logic into the mediator leaves each object with only its core functionality.
  3. Behaviour distributed across classes should be customizable without subclassing them: When the way objects cooperate needs to change. Only the mediator changes, or is subclassed, while the colleague classes stay as they are.
Class Diagram for Mediator Design Pattern
Mediator Design Pattern Class Diagram
Explanation of Mediator Design Pattern's Class Diagram
  • Mediator is the interface through which colleagues communicate; notify(sender, event) tells it that something happened in one colleague.
  • ConcreteMediator knows all the colleagues and implements the coordination logic: when one colleague reports an event, it decides which others should react.
  • Colleague is the base class of the communicating objects. Each colleague holds a reference to the mediator - and only to the mediator.
  • ConcreteColleague1 and ConcreteColleague2 send events to the mediator instead of calling each other, and receive the requests the mediator forwards to them.
Mediator Design Pattern in Java - Class Diagram
Mediator Design Pattern in Java Class Diagram
The example is a chat room. Participants - people and a bot - never send messages to each other directly; they send them to the room, which delivers each message to everyone else.
Code for the classes shown in Java Example's Class Diagram
ChatMediator.java - the mediator interface
//ChatMediator.java
public interface ChatMediator {
 void join(Participant participant);
 void broadcast(String message, Participant from);
}
ChatRoom.java - the concrete mediator
//ChatRoom.java
import java.util.ArrayList;
import java.util.List;

public class ChatRoom implements ChatMediator {
 private final List<Participant> participants = new ArrayList<>();

 public void join(Participant participant) {
  broadcast(participant.name + " joined the room", null);
  participants.add(participant);
 }

 public void broadcast(String message, Participant from) {
  for (Participant p : participants) {
   if (p != from) p.receive(message, from);       // everyone except the sender
  }
 }
}
Participant.java - the colleague, with Member.java and Bot.java
//Participant.java
public abstract class Participant {
 protected final String name;
 protected final ChatMediator room;               // the only object a participant talks to

 protected Participant(String name, ChatMediator room) {
  this.name = name;
  this.room = room;
  room.join(this);
 }

 public void send(String message) {
  room.broadcast(message, this);
 }

 public abstract void receive(String message, Participant from);
}
//Member.java
class Member extends Participant {
 Member(String name, ChatMediator room) { super(name, room); }
 public void receive(String message, Participant from) {
  String sender = from == null ? "room" : from.name;
  System.out.println("  " + name + " sees [" + sender + "]: " + message);
 }
}
//Bot.java
class Bot extends Participant {
 Bot(String name, ChatMediator room) { super(name, room); }
 public void receive(String message, Participant from) {
  if (from != null && message.toLowerCase().contains("help")) {
   send("Hi " + from.name + ", type /rules to see the room rules.");   // reacts through the mediator too
  }
 }
}
ChatApp.java (with the main() method)
//ChatApp.java
public class ChatApp {
 public static void main(String[] args) {
  ChatMediator room = new ChatRoom();
  Participant bot = new Bot("HelpBot", room);
  Participant tom = new Member("Tom", room);
  Participant harry = new Member("Harry", room);

  System.out.println("Tom sends a message:");
  tom.send("Hello everyone!");
  System.out.println("Harry asks for help:");
  harry.send("Can someone help me?");
 }
}
 OUTPUT on running ChatApp.java
  Tom sees [room]: Harry joined the room
Tom sends a message:
  Harry sees [Tom]: Hello everyone!
Harry asks for help:
  Tom sees [HelpBot]: Hi Harry, type /rules to see the room rules.
  Harry sees [HelpBot]: Hi Harry, type /rules to see the room rules.
  Tom sees [Harry]: Can someone help me?
Explanation of Java Example's Class Diagram & Code
  • ChatMediator is the mediator interface, and ChatRoom the concrete mediator, which keeps the list of participants and delivers each message to everyone except its sender.
  • Participant is the colleague. A participant knows only its room: send() hands the message to the room, and receive() is called by the room.
  • Member and Bot are concrete colleagues. A member prints what it receives; the bot reacts to messages containing "help" - and replies through the room as well, so it never needs a reference to Harry.
  • Joining is also coordinated by the mediator: when Tom and Harry join, the room announces them to the participants already present.
  • Notice the order of the output: the bot's reply reaches Tom before Harry's question does. The room delivers messages synchronously, the bot is first in its list, and the bot replies while the room is still delivering Harry's message. Ordering rules like this are exactly the kind of decision which belongs in the mediator - a real chat room would queue messages and deliver them one at a time.
  • No participant refers to any other. Adding a new kind of participant, or changing the rules - private messages, muting, moderation - only touches ChatRoom or the new class.
Note - Mediator and ObserverClick to read: Observer are often used together, and are easy to confuse. An observer subject broadcasts its own changes to whoever subscribed, without caring who they are; a mediator actively coordinates a group of colleagues and contains the logic of how they interact. In a GUI, a dialog object which enables and disables its fields based on each other's values is a classic mediator. The trade-off is that the mediator can grow into a large class which knows too much; keep it focused on coordination.
Summary In the above tutorial we understood what is Mediator design pattern and the main scenarios in which it is applicable. We then looked at the UML class diagram for Mediator Design Pattern & its explanation, a Java use case implementing a chat room with its class diagram, code and output, followed by an explanation of both the class diagram & code. This concludes the tutorial on Mediator design pattern.