Monday, April 22, 2024

Mediator Design Pattern in C#

The Mediator Design Pattern is a behavioral design pattern that promotes loose coupling between objects by encapsulating how they interact. It centralizes complex communication logic between multiple objects into a mediator object, thus reducing direct dependencies between them. This promotes easier maintenance and scalability of the system.

The Mediator Design Pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object. This pattern is used to centralize complex communications and control between related objects in a system. The Mediator object acts as the communication center for all objects. That means when an object needs to communicate with another object, it does not call the other object directly. Instead, it calls the mediator object, and it is the responsibility of the mediator object to route the message to the destination object.

Components of Mediator Design Pattern

  1. Mediator: Defines an interface for communication between colleague objects.
  2. Colleague: It is an abstract class, and Concrete Colleague classes will implement this abstract class.
  3. ConcreteMediator: Implements the mediator interface, coordinating communication between colleague objects.
  4. ConcreteColleague: Implements the colleague interface and communicates with other colleagues through the mediator.

Example: Chat Room Application

Let's illustrate the Mediator pattern with a chat room application where users can communicate with each other via messages.

Create Mediator Interface(IChatRoomMediator.cs)
using MediatorDesignPattern.Colleague;
namespace MediatorDesignPattern.Mediator
{
    /// <summary>
    /// Mediator Interface
    /// </summary>
    public interface IChatRoomMediator
    {
        void SendMessage(string message, User user);
        void RegisterUser(User user);
    }
}
Create Concrete Mediator(ChatRoom.cs)
using MediatorDesignPattern.Colleague;
namespace MediatorDesignPattern.Mediator
{
    /// <summary>
    /// Concrete Mediator
    /// </summary>
    public class ChatRoom : IChatRoomMediator
    {
        private List<User> UsersList = new List<User>();
        //The following method simply registers the user with Mediator
        public void RegisterUser(User user)
        {
            //Adding the user
            UsersList.Add(user);
            //Registering the user with Mediator
            user.Mediator = this;
        }
        //The following method is going to send the message in the group i.e. to the group users
        public void SendMessage(string message, User user)
        {
            foreach (User u in UsersList)
            {
                //Message should not be received by the user sending it
                if (u != user)
                {
                    u.Receive(message);
                }
            }
        }
    }
}
Create Colleague Abstract Class(User.cs)
using MediatorDesignPattern.Mediator;
namespace MediatorDesignPattern.Colleague
{
    /// <summary>
    /// Colleague Abstract Class
    /// </summary>
    public abstract class User
    {
        //This Property holds the name of the user
        protected string Name;
        //This Property is going to set and get the Mediator Instance
        //This Property value is going to be set when we register a user with the Mediator
        public IChatRoomMediator Mediator { get; set; }

        //Initializing the name using Constructor
        public User(string name)
        {
            Name = name;
        }
        //The following Methods are going to be Implemented by the Concrete Colleague
        public abstract void Send(string message);
        public abstract void Receive(string message);
    }
}
Create Concrete Colleague Class(ConcreteUser.cs)
namespace MediatorDesignPattern.Colleague
{
    /// <summary>
    /// Concrete Colleague
    /// </summary>
    public class ConcreteUser : User
    {
        //Parameterized Constructor is required to set the base class Name Property
        public ConcreteUser(string Name) : base(Name)
        {
        }
        //Overriding the Receive Method
        //This method is going to use by the Mediator to send the message to each member of the group
        public override void Receive(string message)
        {
            Console.WriteLine(this.Name + ": Received Message: " + message);
        }
        //This method is used to send the message to the Mediator by a user
        public override void Send(string message)
        {
            Console.WriteLine(this.Name + ": Sending Message = " + message + "\n");
            Mediator.SendMessage(message, this);
        }
    }
}
Client Code(Program.cs)
//Create an Instance of Mediator i.e. Creating a Facebook Group
using MediatorDesignPattern.Colleague;
using MediatorDesignPattern.Mediator;

IChatRoomMediator mediator = new ChatRoom();

//Create instances of Colleague i.e. Creating users
User Ram = new ConcreteUser("Ram");
User Dave = new ConcreteUser("Dave");
User Smith = new ConcreteUser("Smith");
User Rajesh = new ConcreteUser("Rajesh");

//Registering the users with the Mediator i.e. Facebook Group
mediator.RegisterUser(Ram);
mediator.RegisterUser(Dave);
mediator.RegisterUser(Smith);
mediator.RegisterUser(Rajesh);
//One of the users Sending one Message in the Group
Dave.Send("Hello, everyone!");
Console.WriteLine();
//Another user Sending another Message in the Group
Rajesh.Send("Hi, Smith!");
Console.ReadLine();

Outpput

Mediator Design Pattern

In this example, the ChatRoom acts as the mediator, facilitating communication between users (User). Users send messages through the Send method, and the ChatRoom relays these messages to all other users except the sender. This way, users are decoupled from each other, and the communication logic is centralized in the ChatRoom.

Conclusion

The Mediator Design Pattern is useful when you have a set of objects with complex communication logic. By centralizing this logic in a mediator, it promotes loose coupling and simplifies maintenance and scalability. It's particularly handy in scenarios like chat applications, where multiple entities need to communicate without creating tight dependencies between them.

The full source code is available here:

Happy coding!! 😊

No comments:

Post a Comment

^ Scroll to Top