The Mediator pattern is intended to define an object that encapsulates how a set of objects interacts. Object do not communicate directly with eachother, but through a mediator. This reduces the dependencies between communicating objects.
The client instantiates the communicating objects, so called colleagues, and a mediator through which they are communicating.
Colleague c1 = new ConcreteColleague1(m); Colleague c2 = new ConcreteColleague2(m); Mediator m = new ConcreteMediator(); m.AddColleague(c1); m.AddColleague(c2); c1.Send(c2, "Hello, c2. Are you there?"); c2.Send(c1, "No, goodbye!");
The abstract class Colleague contains a Mediator, which is injected at instantiation. In this example, it has two methods for communication. One for sending a message, the other for receiving a message.
abstract class Colleague
{
protected Mediator mediator;
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
abstract public void Send(Colleague to, string message);
abstract public void Received(Colleague from, string message);
}
The abstract class Mediator contains an internal store for colleages and a method for adding colleagues. It also contains an abstract method for sending a message to the preferred colleague.
abstract class Mediator
{
protected List colleagues = new List();
public void AddColleague(Colleague colleague)
{
colleagues.Add(colleague);
}
public abstract void Send(Colleague colleague, string message);
}
The concrete class implements the abstract method. In this case, it forwards the message to the selected colleague.
class ConcreteMediator : Mediator
{
public override void Send(Colleague to, string message)
{
to.Received(to,message);
}
}
Finally, the selected concrete colleague receives the message. I only show the concrete class ConcreteColleague1, since ConcreteColleague2 is almost identical to this one. So if you want to try this code, I suggest you do a search and replace on ConcreteColleague1.
class ConcreteColleague1 : Colleague
{
public ConcreteColleague1(Mediator mediator)
: base(mediator) { }
override public void Send(Colleague to, string message)
{
Console.WriteLine("Sending message (ConcreteColleague1)-----------------------------");
Console.WriteLine("To : " + to.GetType().Name);
Console.WriteLine("Message: " + message);
Console.WriteLine();
mediator.Send(to,message);
}
override public void Received(Colleague from, string message)
{
Console.WriteLine("Receiving message (ConcreteColleague1)---------------------------");
Console.WriteLine("From : " + from.GetType().Name);
Console.WriteLine("Message: " + message);
Console.WriteLine();
}
}
This post is part of a series on the foundational design patterns in C#. In this series we explore the ancient design patterns and their use in real-world programming situations of today. In these series of posts we explore each pattern by looking at a minimalistic example to reveal its structure and then look at more concrete and useful real-world C# code that implements the pattern.


