Mediator Design Pattern | Java Implementation

Mediator pattern is a Behavioral Design pattern. It is used to handle complex communications between related Objects, helping by decoupling those objects.

Intent

Mediator pattern defines an object that encapsulates how a set of objects interact. Mediator promotes loose coupling of Objects by keeping them from referring to each other directly, and it lets you vary their interaction independently.

So, simply said, it basically lets you control the communication between each object. As the name implies: mediator.

Mediator Pattern is useful for Enterprise Applications where multiple modules are communicating with each other, If the modules interact with each other directly, then the modules will be tightly coupled. As a result, maintenance of these modules will be more difficult and make them non extendable.

Real World Example

This pattern defines a mediator object that controls how a set of objects interacts. The objects which are communicating via the mediator are called as colleague objects. Loose coupling between colleague objects is achieved by having colleagues communicate with the Mediator, rather than with each other.

An airport control tower is an excellent example of the mediator pattern. The pilots of the arriving planes or departing the terminal area communicate with the tower rather than explicitly communicating with one another. Here the control tower is acting as a mediator and the planes are the colleague objects. This idea of a central controller is one of the key aspects of the mediator pattern.

Class Diagram

As we have already discussed that mediator pattern relies on a central controller aka mediator and the colleague objects. The colleague objects need to communicate with each other which is accomplished via the mediator. Now let’s have a look in the class diagram. The key player in Mediator pattern are the mediator itself and the colleague classes. The mediator defines an interface as an abstraction. This abstraction layer is used for communicating with the colleague objects. The concrete mediator implements cooperative behavior by coordinating with the colleague objects. Next we have our colleague classes. Each colleague class knows the mediator object and each colleague communicates with its mediator only when it requires to communicate with other colleague objects.

Java Implementation of Mediator Pattern:

Now let us understand this pattern with a real implementation. The chat box application is an example of the mediator pattern. Several participants can join a chat box for discussion on some topic. Now it is not feasible or scalable to connect each participant to all other participant in that chat-box. In such scenario the number of connections will be too high. To solve this problem, we can use the mediator pattern, where the chat-box is the mediator and all the participants are the colleague objects. The participants never communicate directly to each other, they will interact via the chat-box when required. Lets check the implementation here:

First of all we will create Mediator interface ChatBox that will define the contract for concrete mediators.

package com.tuturself.dp.mediator;

public interface ChatBox {

	/*
	 * Contract method for message
	 */
	public void sendMessage(Participant sender, String msg);

	/*
	 * Contract method for add Subscriber
	 */
	void addParticipant(Participant participant);
}

Now we will define the Mediator Pattern Colleague Interface. Where the participant can send and receive messages, so we can have Participant abstract class.

package com.tuturself.dp.mediator;

public abstract class Participant {

	protected ChatBox chatBox;
	protected String name;

	public Participant(ChatBox chatBox, String name) {
		this.chatBox = chatBox;
		this.name = name;
	}

	/*
	 * Contract method to send notification message.
	 */
	public abstract void send(String msg);

	/*
	 * Contract method to receive new notification message.
	 */
	public abstract void receive(Participant sender, String msg);

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Participant other = (Participant) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}

Now we will create concrete mediator class ChatBoxImpl , it will have a list of participants in the group and provide logic for the communication between them.

package com.tuturself.dp.mediator;

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

public class ChatBoxImpl implements ChatBox {

	private List<Participant> participantList = new ArrayList<>();

	@Override
	public void sendMessage(Participant sender, String msg) {
		for (Participant p : participantList) {
			if (!p.equals(sender)) {
				p.receive(sender, msg);
			}
		}
	}

	@Override
	public void addParticipant(Participant participant) {
		participantList.add(participant);
	}
}

Now we can create concrete Colleague classes named as ParticipantImpl to be used by client system.

package com.tuturself.dp.mediator;

public class ParticipantImpl extends Participant {

	public ParticipantImpl(ChatBox chatBox, String name) {
		super(chatBox, name);
	}

	@Override
	public void send(String msg) {
		System.out.println("------------------------------------------");
		System.out.println(this.name + " :: Sending Message :: " + msg);
		System.out.println("------------------------------------------");
		chatBox.sendMessage(this, msg);
	}

	@Override
	public void receive(Participant sender, String msg) {
		System.out.println("ChatBox >> " + this.name);
		System.out.println("Message From : " + sender.name);
		System.out.println("Message : " + msg);
		System.out.println("________________________");
	}
}

Let’s test this our chat application with a simple program where we will create mediator and add participants to the group and they will send messages to other participants.

package com.tuturself.dp.mediator;

public class JavaChatBoxApplication {

	public static void main(String[] args) {
		ChatBoxImpl mediator = new ChatBoxImpl();
		Participant p1 = new ParticipantImpl(mediator, "Ninja Panda");
		Participant p2 = new ParticipantImpl(mediator, "Ninja AK");
		Participant p3 = new ParticipantImpl(mediator, "Master Shifu");
		Participant p4 = new ParticipantImpl(mediator, "Ninja F6F8");
		
		mediator.addParticipant(p1);
		mediator.addParticipant(p2);
		mediator.addParticipant(p3);
		mediator.addParticipant(p4);

		p1.send("Hello World");
		p2.send("Hey, What is an abstract class?");
	}
}

Output of the mediator pattern example program is:

------------------------------------------
Ninja Panda :: Sending Message :: Hello World
------------------------------------------
ChatBox >> Ninja AK
Message From : Ninja Panda
Message : Hello World
________________________
ChatBox >> Master Shifu
Message From : Ninja Panda
Message : Hello World
________________________
ChatBox >> Ninja F6F8
Message From : Ninja Panda
Message : Hello World
________________________
------------------------------------------
Ninja AK :: Sending Message :: Hey, What is an abstract class?
------------------------------------------
ChatBox >> Ninja Panda
Message From : Ninja AK
Message : Hey, What is an abstract class?
________________________
ChatBox >> Master Shifu
Message From : Ninja AK
Message : Hey, What is an abstract class?
________________________
ChatBox >> Ninja F6F8
Message From : Ninja AK
Message : Hey, What is an abstract class?
________________________

 

CORE JAVA BEHAVIOURAL-PATTERNS