Introducing the Mediator design pattern

Introducing the Mediator design pattern

Read Time : 4 Minutes

Saturday, 18 March 2023

Design patterns are proven solutions to software design problems. They help improve code quality, promote reusability, and increase maintainability. We use them to save time and produce quality, extensible and flexible code. In this article, we are going to introduce the Mediator design pattern.

The Mediator design pattern is a behavioral design pattern that enables loose coupling between different components by providing a central communication container. This interface object is responsible for managing communication between different components.

The Mediator pattern consists of several components:

  • Mediator: Defines an interface for communication between objects.
  • ConcreteMediator: Implements the Mediator interface and establishes communication between objects.
  • Colleague: An interface that objects used in Mediator must implement.
  • ConcreteColleague: Objects used in Mediator. These objects implement the Colleague interface.
mediator gof

The Mediator pattern can be useful in systems where objects are highly interconnected. By defining a Mediator object, direct communication between objects is reduced, making the system more flexible and easier to maintain.

For example, consider a system that contains many components that must communicate with each other. Without the Mediator pattern, these components must communicate directly with each other, leading to strong dependencies between them. Using the Mediator pattern, components communicate through a central Mediator object, which reduces dependencies and makes code easier to manage.

mediator

Here is a sample C# code for the Mediator design pattern:

// Mediator interface
interface IMediator
{
    void Notify(object sender, string eventName);
}
// Colleague abstract class
abstract class Colleague
{
    protected IMediator mediator;
    public Colleague(IMediator mediator)
    {
        this.mediator = mediator;
    }
}
// Concrete colleague class
class ConcreteColleagueA : Colleague
{
    public ConcreteColleagueA(IMediator mediator) : base(mediator) { }
    public void Send(string message)
    {
        Console.WriteLine("Colleague A sends message: " + message);
        mediator.Notify(this, "MessageA");
    }
    public void Receive(string message)
    {
        Console.WriteLine("Colleague A receives message: " + message);
    }
}
// Concrete colleague class
class ConcreteColleagueB : Colleague
{
    public ConcreteColleagueB(IMediator mediator) : base(mediator) { }
    public void Send(string message)
    {
        Console.WriteLine("Colleague B sends message: " + message);
        mediator.Notify(this, "MessageB");
    }
    public void Receive(string message)
    {
        Console.WriteLine("Colleague B receives message: " + message);
    }
}
// Concrete mediator class
class ConcreteMediator : IMediator
{
    private ConcreteColleagueA colleagueA;
    private ConcreteColleagueB colleagueB;
    public void SetColleagueA(ConcreteColleagueA colleagueA)
    {
        this.colleagueA = colleagueA;
    }
    public void SetColleagueB(ConcreteColleagueB colleagueB)
    {
        this.colleagueB = colleagueB;
    }
    public void Notify(object sender, string eventName)
    {
        if (sender == colleagueA && eventName == "MessageA")
        {
           colleagueB.Receive("MessageA");
        }
        else if (sender == colleagueB && eventName == "MessageB")
        {
            colleagueA.Receive("MessageB");
        }
    }
}
// Client class
class Client
{
    static void Main(string[] args)
    {
        // Create mediator and colleagues
        ConcreteMediator mediator = new ConcreteMediator();
        ConcreteColleagueA colleagueA = new ConcreteColleagueA(mediator);
        ConcreteColleagueB colleagueB = new ConcreteColleagueB(mediator);
        // Set colleagues on mediator
        mediator.SetColleagueA(colleagueA);
        mediator.SetColleagueB(colleagueB);
        // Send messages between colleagues
        colleagueA.Send("Hello from Colleague A");
        colleagueB.Send("Hi from Colleague B");
        Console.ReadKey();
    }
}

In this example, we have a Mediator interface that defines a Notify method to communicate between objects. The Colleague abstract class defines an IMediator field and gets it through the constructor method. ConcreteColleagueA and ConcreteColleagueB are two implementations of the Colleague class and have a Send method to send messages to the Mediator and a Receive method to receive messages from the Mediator.

The ConcreteMediator class implements the IMediator interface and holds the desired objects, ConcreteColleagueA and ConcreteColleagueB. It also implements the Notify method to manage communication between objects.

Finally, in the Client class, we create Mediator and Colleague objects, then introduce the objects to the mediator. If the desired methods are called, the communication of objects is done through the Mediator.

 

In short, the Mediator pattern eliminates the direct connection between objects by centralizing communication through a central object and makes the system easier to manage.

To read about other design patterns, you can use the list below. There is also a code repository on GitHub that includes all the design patterns.

design patterns

Creational:Factory Design Pattern
Builder Design Pattern
Singleton Design Pattern
Prototype Design Pattern
Abstract Factory Design Pattern
Structural:Adapter Design Pattern
Bridge Design Pattern
Composite Design Pattern
Decorator Design Pattern
Facade Design Pattern
Flyweight Design Pattern
Proxy Design Pattern
Behavioral:Chain of Responsibility Design Pattern
Command Design Pattern
Interpreter Design Pattern
Mediator Design Pattern
Memento Design Pattern
Observer Design Pattern
State Design Pattern
Strategy Design Pattern
Template Method Design Pattern
Visitor Design Pattern
Iterator Design Pattern
  • Share:
reza babakhani
Reza Babakhani

I am Reza Babakhani, a software developer. Here I write my experiences, opinions and suggestions about technology. I hope that what I write is useful for you.

Latest post

Service Mesh Simplifying Microservice Communication

In the ever-evolving landscape of software development, microservices architecture has gained considerable popularity due to its scalability, flexibility, and extensibility. However, as the number of microservices in an application increases, it becomes increasingly challenging to manage their communication and ensure that they are all properly visible. This is where Service Mesh comes into play.

The Importance of Edge Computing

Due to the speed of technological evolution, one of the concepts that has attracted a lot of attention and changes the way we interact with digital systems is edge computing.

What is event-driven architecture?

Event-driven architecture (EDA) is a software design pattern that has become increasingly popular in modern software development. In this architecture, the flow of data is determined by the occurrence of events. Unlike traditional centralized systems that are constantly checking for new status. Event-driven architecture is especially useful for systems that need to process large amounts of data in real-time.

leave a comment