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.

image

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.