Girish Managoli, Avijeet
Dash and Satyabrata Dash
Intent
Define an object that encapsulates how a set of objects interact. Mediator
promotes loose coupling by keeping objects from referring to each other
explicitly, and it lets you vary their interaction independently.
In 30 Seconds
The catch here is, "objects interacting through a central controller,
instead of interacting with each other directly".
Dividing the functionality and behavior into several classes enhances
reusability of the classes. This also helps in keeping the classes small,
modular and maintainable. However, as the number of classes increase, the
interactions and dependencies between the classes also increase. This makes the
system difficult to maintain and change. The idea here is to introduce a
"controller" class, through which all the other objects interact. All
classes depend only on the controller class; only the controller class knows
about all classes. The "controller" class is called Mediator.
Motivation
Concentrating the complexity in one class can reduce the overall complexity
of a system. The Mediator is the "know-all" class that decides how the
objects interact. The objects themselves are responsible for carrying out their
assigned tasks and know nothing about the other objects but the Mediator. This
enables the objects to be re-used in other systems independently of other
objects. Also, since the Mediator decides how the objects interact, replacing
the Mediator brings a different behavior in the system.
Structure
Click Here to
view picture
Examples
Example 1:
Let us say we are implementing a dialog like this:
(Actual dialog to be implemented in Java)
The text field "Spouse Name" is enabled if "Yes" radio
button is clicked.
Java Swing provides the GUI components that are designed to be reusable
components without any dependency between them. We have to implement a
"Mediator" class that controls how the components interact. Mediator
has to implement the ActionListener interface and gets notified when
"Yes" option is selected. The Mediator sends a signal to "Spouse
Name" text field to enable it. The class diagram and sequence diagram below
depict the object interactions.
Click Here to
view picture
Click Here to
view picture
Thoughts
The Mediator can share a common interface as shown in the structure above.
This enables replacing the ConcreteMediator class to allow a different behavior.
Also the Colleague classes can be effectively reused without having to be
rewritten for a new Mediator class.
There may be cases when a common Mediator interface is not necessary, when
the common interface can be avoided.
There is no necessity for the Colleague classes to share the same interface.
This only makes the pattern more restrictive. The Colleagues can conveniently be
unrelated set of classes.
In general, Mediator pattern is very effective and useful for building a low
coupling system by reducing the number of interactions between the objects, thus
enhancing the overall system testability, reusability and maintainability.
Sample Code
// Colleague.java
//
abstract class Colleague
{
private Mediator _aMediator;
public Colleague(Mediator m)
{
_aMediator = m;
}
public void changed()
{
_aMediator.colleagueChanged(this);
}
public Mediator getMediator()
{
return(_aMediator);
}
public abstract void Display();
}
// Mediator.java
//
import java.io.*;
abstract class Mediator
{
public abstract void colleagueChanged(Colleague theChangedColleague);
public
static void main(String
args<>)
{
ConcreteMediator aConcreteMediator = new ConcreteMediator();
aConcreteMediator.createConcreteMediator();
(aConcreteMediator.getOneColleage()).Display();
(aConcreteMediator.getNextColleague()).Display();
OneColleague newColleague = new OneColleague(aConcreteMediator,
"OneColleague");
aConcreteMediator.colleagueChanged( (OneColleague)newColleague
);
(aConcreteMediator.getOneColleage()).Display();
(aConcreteMediator.getNextColleague()).Display();
}
}
// ConcreteMediator.java
//
class ConcreteMediator extends Mediator
{
private OneColleague _aOneColleague;
private NextColleague _aNextColleague;
public void colleagueChanged( Colleague theChangedColleague )
{
if ((( OneColleague)theChangedColleague).getSelection().equals(
_aOneColleague.getSelection() ) )
{
_aNextColleague.setText( _aOneColleague.getSelection() );
}
}
public void createConcreteMediator()
{
_aOneColleague = new OneColleague(this, "OneColleague");
_aNextColleague = new NextColleague(this, "NextColleague");
}
// OneColleague.java
//
class OneColleague extends Colleague
{
private String _text;
public OneColleague(Mediator m, String t)
{
super( m );
_text = t;
}
public void setText(String text)
{
_text = text;
}
public String getSelection()
{
return(_text);
}
public void Display()
{
System.out.println("OneColleague = " + _text);
}
}
// NextColleague.java
//
class NextColleague extends Colleague
{
private String _text;
public NextColleague(Mediator m, String t)
{
super( m );
_text = t;
}
public void setText(String text)
{
_text = text;
}
public String getSelection()
{
return( _text );
}
public void Display()
{
System.out.println("NextColleague = " + _text);
}
}
Whenever the mediator's colleagueChanged() method is called (with a new
Colleague passed in as an argument), it compares the contents of the new
colleague with the contents of one of its colleagues (the OneColleague). If
there is a match it sets the contents of its other colleague (the NextColleague)
to match the first colleague (the OneColleague).
Complexities simplified
Omitting the Abstract Mediator Class
There’s no need to define an abstract Mediator class when colleagues work
with only one mediator.
Colleague-Mediator communication
Colleagues have to communicate with their mediator when an event of interest
occurs. One approach is to implement the mediator as an Observer pattern.
Colleague classes act as subjects, sending notifications to the mediator
whenever they change state.
The other approach is to define a specialized notification interface in
Mediator that lets colleagues be more direct in their communication.
Related Patterns
Facade and Mediator are similar; both result in a low coupling system. Facade
provides a simplified interface to a subsystem. The message flow in Facade is
unidirectional; clients make calls to the subsystem and not vice versa.
Mediator, in contrast, enables cooperative interaction between the objects and
message flow is multidirectional.
Colleagues can communicate with Mediator using Observer pattern.