Thursday, October 25, 2012

Clarifying Mediator pattern

Introduction

Mediator is design pattern that is primarily used to loose coupling between components in their communication. For instance, if each of components would communicate to each other directly, we could get a complex net of communication lines between these components. Instead of direct communication we are using mediator who will be intermediate component for inside communication between components.Simple scenario for mediator role would be to gather messages from each component (component is in some books referred as Colleague), and than mediator would broadcast that message to all other components.In the next image we can see UML class diagram showing us dependencies between classes in implementation of Mediator pattern. Mediator and Component can be either abstract classes or interfaces, depending of the specific implementation.

UML class diagram representing Mediator pattern

Now, there is a question, since mediator using broadcast, how each of components would know that the message is intended just for her. Well, in most cases message contains a key value that would be known to the receiver and sender, and it will be used to determine the originator and receiver of the message. There is also possibility to send sender and recipient information within the message. So, when the message is received by some component, component can determine if the message is intended for her or some other component, in that way message can be processed or ignored.From the security side, this is not very safe way to distribute all messages as a broadcast, but if implementation is not restricted with security rules (for example, UI classes) than it can have a good purpose to decouple communication between components.

Implementation

In this blog I’ll demonstrate simple chat application written in Java. Application will contain three tabs (three components, i.e. Colleague), and each of the tabs will be able to communicate with other tabs over the Mediator. For the message representation I’ll implement Intent class which instances will be able to contain string messages. Of course, current implementation of Intent can be extended and used to wrap other object types in a message as well.

Screenshot of the Mediator demo application

Current implementation of demo project is demonstrated in the next picture:

Now, let’s take a look at the code.This is simple Mediator interface that will be implemented in the Mediator class.

package com.testmediator;

publicinterface IMediator {

public void addComponent(IComponent _component);

public void send(Intent _message, IComponent _sender);

}

Class Mediator implements previous interface with two methods. Method addComponent is used for registering components, since the Mediator needs to know all actors of communication. Second method, send, simply broadcasts message to all of the components, except sender component.

In the next code preview you can see Component interface that will be implemented in Component classes.

package com.testmediator;

public interface IComponent {

public void receive(Intent _message);

public void send(Intent _message, IComponent _sender);

public IMediator getMediator();

}

As you can see in the Component implementation, each Component contains the reference to the same Mediator that is set up in the constructor. Other important methods are send and receive which implements sending message via Mediator instance and receiving message from Mediator broadcast, respectively. On the click of the send button message will be send to another component depending of selected recipient from the combo box.

Simple Intent class represents wrapper for all messages. As you can see for now it contains only methods for putting string message and reading the same message. This class can be extended to wrap all other kinds of objects.

package com.testmediator;

publicclass Intent {

String m_stringMsgKey;

String m_stringMsg = "";

public void putStringMsg(String _key, String _value){

m_stringMsgKey = _key;

m_stringMsg = _value;

}

publicString getStringMsg(String _messageKey){

if(_messageKey == m_stringMsgKey){

return m_stringMsg;

}

else{

return "";

}

}

}

Other classes from project are excluded from code preview since primary role of this blog was to present Mediator pattern. In a context of the project it is basically a simple desktop app developed using swing library.

Conclusion

Mediator pattern is pretty common to meet in a different solutions. For instance, Android platform is using very similar principle regarding communication between Activities using Intent objects as messages that will be broadcasted to all Activity instances in the app. This way complex peer-to-peer communication is replaced by the Mediator who is in charge of distributing messages, providing loose coupling between components which is in the almost all cases very good practice.