Design patterns are documented and tested solutions for recurring problems. They are used to solve the problems of objection creation and integration. Developers encounters these problems on a day to day basis. So, it is a best practice to use design patterns as they are reusable solutions.
It is important to remember that you do not need to over-do design patterns. Design patterns are for projects, projects are not for design patterns. So, use it in the project if you think it is a good fit. Otherwise, It can make your project messy.
Types of Design Patterns
Gang of Four categorised design patterns into three main categories
1. Creational Design Pattern
2. Structural Design Pattern
3. Behavioural Design Pattern
In this blog, we will discuss Mediator design pattern. It is a behavioral design pattern that promotes loose coupling.
Mediator Design Pattern
It is used to reduce communication between objects. This pattern provides a mediator object and that object handles all the communication between objects.
In the following diagram, you can see there are 3 objects(X, Y, and Z). Suppose, object X has to send data to Y and then Y has to send a message to Z. These objects need to know each other. They are tightly coupled. In the real world, there are hundreds and thousands of objects that have to call each other. It makes the on-going management of code an up-hill task.
How Mediator Pattern solves the problem?
If object X has to call object Y and Z. It doesn’t have to call directly. It will call the mediator object and it is the responsibility of the mediator object to pass the message to the destination object. The mediator helps you promote loose coupling by keeping objects from referring and interacting with each other.
Implementation of Mediator Pattern
You can install by Nuget Package Manager
or via .Net core CLI
dotnet add package MediatR
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
I have installed MediatR and MediatR.Extensions.Microsoft.DependencyInjection in my demo project.
Next thing is that you have to inject the mediatR in controller.
The mediator call consists of a request and a handler. Every request has its handler. The request could be anything from a complex object to an integer value.
In the following image, you can see we are making a request to the mediator which takes CreateUserCommand as a model.
Requests are of two types.
1. IRequest<TRequest> – returns TRequest
2. IRequest – returns nothing
A request is a class that has a handler attached to it. You can see in the image below, I have implemented IRequest<TRequest>. CreateUserCommand request takes AppUser as a return value.
Request Handler (Responses) are of two types.
1. IRequestHandler<TRequest, TResponse> – returns TResponse
2. IRequestHandler<TRequest> – returns nothing
You can see in the image below, I have implemented IRequestHandler<TRequest, TResponse>. This handler implements the request of CreateUserCommand and returns AppUser.
The mediator design pattern helps us reduce coupling and promote SOLID principles. You should use it if you think it can be a good fit for your project. I have explained in this blog about the design pattern and its implementation. As a reference, you can find the complete source code in my demo app.