Mediator
The mediator pattern
The mediator pattern is a behavioral pattern and used to prevent coupling between objects that need to exchange information.The pattern's structure is shown in the diagram below, the Colleague uses the Mediator for the information exchange and the Mediator sends the received information to the required Colleagues.
The pattern has many uses, usually utilising the observer pattern and is especially useful for communication between similar clients, like a chat room.
Here's an example, in C#, that shows this approach. Firstly the mediator:
class ChatMediator {
List<Colleague> colleagues;
public ChatMediator() {
colleagues = new List();
}
public void Subscribe(Colleague colleague) {
colleagues.Add(colleague);
}
public void ProcessMessage(Colleague rxColleague, string message) {
foreach(Colleague colleague in colleagues.Where(p => Colleague.CompareForTx(p, rxColleague))) {
colleague.SendMessage(message);
}
}
}
The colleague:
List<Colleague> colleagues;
public ChatMediator() {
colleagues = new List
}
public void Subscribe(Colleague colleague) {
colleagues.Add(colleague);
}
public void ProcessMessage(Colleague rxColleague, string message) {
foreach(Colleague colleague in colleagues.Where(p => Colleague.CompareForTx(p, rxColleague))) {
colleague.SendMessage(message);
}
}
}
class Colleague {
public string Group { get; private set; }
public string Name { get; private set; }
public Colleague(string group, string name) {
Group = group;
Name = name;
}
public void SendMessage(string message) { // callback
Console.WriteLine($"{Name} in {Group} received '{message}'.");
}
public static bool CompareForTx(Colleague colleague1, Colleague colleague2) {
return colleague1.Name.CompareTo(colleague2.Name) != 0 && colleague1.Group.CompareTo(colleague2.Group) == 0;
}
}
Console code to test:
public string Group { get; private set; }
public string Name { get; private set; }
public Colleague(string group, string name) {
Group = group;
Name = name;
}
public void SendMessage(string message) { // callback
Console.WriteLine($"{Name} in {Group} received '{message}'.");
}
public static bool CompareForTx(Colleague colleague1, Colleague colleague2) {
return colleague1.Name.CompareTo(colleague2.Name) != 0 && colleague1.Group.CompareTo(colleague2.Group) == 0;
}
}
static void Main(string[] args) {
ChatMediator chatMediator = new ChatMediator();
Colleague brain = new Colleague("TakeOverWorldGroup", "The Brain");
Colleague pinkey = new Colleague("TakeOverWorldGroup", "Pinkey");
Colleague dick = new Colleague("WackeyRacesGroup", "Dick Dastardly");
Colleague muttley = new Colleague("WackeyRacesGroup", "Muttley");
Colleague penelope = new Colleague("WackeyRacesGroup", "Penelope Pitstop");
chatMediator.Subscribe(brain);
chatMediator.Subscribe(pinkey);
chatMediator.Subscribe(dick);
chatMediator.Subscribe(muttley);
chatMediator.Subscribe(penelope);
chatMediator.ProcessMessage(penelope, "Heeelp Heeeelp");
chatMediator.ProcessMessage(pinkey, "What will we do tomorrow?");
chatMediator.ProcessMessage(muttley, "He He He He He");
chatMediator.ProcessMessage(brain, "We will do as we always do...");
chatMediator.ProcessMessage(pinkey, "What's that?");
chatMediator.ProcessMessage(brain, "TOMMOROW WE WILL TRY TO TAKE OVER THE WORLD!!!!");
chatMediator.ProcessMessage(dick, "Shut up!");
Console.ReadKey();
}
And the console output:
ChatMediator chatMediator = new ChatMediator();
Colleague brain = new Colleague("TakeOverWorldGroup", "The Brain");
Colleague pinkey = new Colleague("TakeOverWorldGroup", "Pinkey");
Colleague dick = new Colleague("WackeyRacesGroup", "Dick Dastardly");
Colleague muttley = new Colleague("WackeyRacesGroup", "Muttley");
Colleague penelope = new Colleague("WackeyRacesGroup", "Penelope Pitstop");
chatMediator.Subscribe(brain);
chatMediator.Subscribe(pinkey);
chatMediator.Subscribe(dick);
chatMediator.Subscribe(muttley);
chatMediator.Subscribe(penelope);
chatMediator.ProcessMessage(penelope, "Heeelp Heeeelp");
chatMediator.ProcessMessage(pinkey, "What will we do tomorrow?");
chatMediator.ProcessMessage(muttley, "He He He He He");
chatMediator.ProcessMessage(brain, "We will do as we always do...");
chatMediator.ProcessMessage(pinkey, "What's that?");
chatMediator.ProcessMessage(brain, "TOMMOROW WE WILL TRY TO TAKE OVER THE WORLD!!!!");
chatMediator.ProcessMessage(dick, "Shut up!");
Console.ReadKey();
}
Dick Dastardly in WackeyRacesGroup received 'Heeelp Heeeelp'.
Muttley in WackeyRacesGroup received 'Heeelp Heeeelp'.
The Brain in TakeOverWorldGroup received 'What will we do tomorrow?'.
Dick Dastardly in WackeyRacesGroup received 'He He He He He'.
Penelope Pitstop in WackeyRacesGroup received 'He He He He He'.
Pinkey in TakeOverWorldGroup received 'We will do as we always do...'.
The Brain in TakeOverWorldGroup received 'What's that?'.
Pinkey in TakeOverWorldGroup received 'TOMMOROW WE WILL TRY TO TAKE OVER THE WORLD!!!!'.
Muttley in WackeyRacesGroup received 'Shut up!'.
Penelope Pitstop in WackeyRacesGroup received 'Shut up!'.
One thing of note about my example is that the Colleague is completely unaware of the mediator.
Summary
The mediator pattern is a simple pattern and very similar to the
observer pattern
but decides which object(s) receives a response according to some criteria.
A problem with the pattern is that, if the colleagues have many different reasons for a reply then
the mediator can become very large and complex.