Design patterns: Mediator

Today it was supposed to be about an operational pattern called Mediator, which satisfies the last SOLID principle, namely avoiding dependencies between classes, here we create one class that can be said is an interface to all elements of the system, we pass only commands to this interface and it handles the transfer , the mediator is certainly a pattern worth knowing … 💪 so we’re going with the topic 🙂.

 

Admission

Soon we will go to a specific Mediator discussion, only a small news, after the publication of this entry may not be another entry for a month, two months or more, because I would like to deal more with the translation of this blog so that not only Polish had access to it and I would like to improve its functionality and some other entries and of course I also have other projects and I would like a little rest 😓 , so it may take a while, the blog treats temporarily as an add-on, as I said I have other projects, but it should change in the future because I like to help others. Ok, let’s get to the facts 🙂

 

Discussion

The Mediator pattern gives a uniform interface for sending messages between classes, this interface contains all references to these classes, i.e. it simply reduces the number of dependencies between them, if for example we need a dependency or element from another class, we send a command to the mediator interface, and this returns us appropriate value.

If we wanted to write dependencies in the traditional way, i.e. simply to stuff dependencies to classes that depend on these dependencies, then there is a tangle of dependencies in these classes let us assume that we have group of three people who are administers, devs and users, the dependencies look like this as below in the picture.

Mediator example

A tangle of dependencies emerges from such a traditional operation, it is unacceptable in larger projects. And if we used the Mediator pattern then we would have something like this:

Mediator example

And you can see that it not only looks better and is much clearer by that arrangement objects do not know about themselves and the less objects know about themselves the better, there is less probability of error and if they want to get some dependence from another class they just send command to the mediator interface and this one returns the appropriate value.

 

Intent

  • Reducing the number of connections between classes.
  • Encapsulation of objects using the mediator interface.
  • Providing a unified interface to managing dependencies between classes.

 

Problem

It is best to use the mediator’s pattern in situations where we have many dependencies between classes, and so-called spaghetti code is created, which is difficult to understand 🙂 . It’s best to learn as fast as you can how to write a non-spaghetti code. 😐

 

Use when:

  • You want to get rid of many dependencies between classes.
  • You want to encapsulate classes so that they do not know about themselves, only took dependencies through the mediator class.
  • You want to have one interface in which all class references will be collected.

 

Advantages and disadvantages

Advantages

  • Loose relationships between objects in the system.
  • Dependencies between objects are flexible, it is possible to easily develop dependencies.
  • Because the whole logic is encapsulated in the mediator class, if we need to add a dependency to a class, we only need to expand the mediator class.
  • Simplified communication between classes, because if a class wants to communicate with some other classes, it only has to send a command to the mediator class.

 

Disadvantages

  • Complicating the Mediator class, if there are too many dependencies in it, which will be responsible for everything, similarly works on the first SOLID principle, i.e. if Mediator class dependencies are responsible only for communication, it is better that there are no dependencies in this class responsible for something else, because then Mediator classes will be very complicated.

 

That’s a bit of it is, I’m aware of it, that’s why I’ll tell prank, so that I and you will also rest. 🙂😂

The patient comes to the doctor and asks:

– Doctor, how long will I live !?

-Hmm, are you drinking?

-No! I never drank !!

– Have you smoke?

-No! Also never!

-Some women did you have?

– No! So, Doctor, how long will I live ?!

– Hundred years I think … but why the f**k like that?

Well, the end of the prank 😂, let’s move on 🙂

 

Structure

The general UML diagram of the Mediator pattern looks like this:

Mediator scheme

It shows that the classes communicate through the Mediator class, but usually the detailed implementation of the Mediator pattern looks like in the diagram below:

Mediator scheme

In the diagram above, the classes inheriting from the Widget class, ie Table, Tree, CheckBox, use the Intermediary class, which is the equivalent of the Mediator class from the first diagram.

In the code, the mediator pattern looks more or less like the one below. As usual, in the structure area gives a simple example to make it easy to understand, let’s start with the Mediator class:

We see that arguments are sent to the Send() method and, depending on the type of class passed, pass the message variable to the appropriate class. At the top, we have the Colleague type set twice, so that we do not create a specific class type, and we pass concrete objects to the ConcreteMediator class in the client.

And also ConcreteColleague1 and ConcreteColleague2 classes.

When we return to the client, Send() methods are called in the ConcreteColleague1 and ConcreteColleague2 classes, which only forward the message to the ConcreteMediator class and depending which class invoked the Send() method, the corresponding message from the Notify() method is displayed.

Result:

 

Real-life examples

Chat

The first such example will be chat, for example, if we were to divide the code into classes according to each chat user, and for each of them to assign dependencies, the dependencies between them would be very tangled, and in this example it is good to use a mediator if a person sends a message, she is transferred to the mediator’s class and then passed to the appropriate person who was to receive the message. And all dependencies we have in one class, beautifully simple, clear and effective.

Let’s see how it looks in the code, let’s start with the mediator class.

The principle of the mediator’s class is the same as in the previous example only the implementation is different, here we do not assign on stiffly the dependencies only with the Register() method. We register dependencies on a regular basis, check if there is such a dependency in the class, if not, we write it to the dictionary.

And in the Send() method we check if there is a registered person with name, which we passed to the Send() method in the chat, if so we send a message to it.

Let’s see what the Participant class looks like, which we defined in the dictionary.

The most important thing in this class is that we write down the name of the participant in it and forward the message to the Send() method in the Participant class and then further forward the message to the Send() method in the Chatroom class, and we have the Receive() and Notify() methods defined.

As I divided participants according to their gender, we have separate classes for them.

And in these classes we have defined Receive() and Notify() methods.

Finally, the customer.

And you can see that in the client we register chat users and send messages.

Result:

 

Control platform

Another example is the flight control tower, I bet that the software uses Mediator 🙂 there, this tower controls the flight of every plane, helicopter, etc. This is well illustrated by the picture below.

Mediator example

Let’s start as in the previous example about the chat from the mediator class.

The principle of operation and implementation, identical to the chat example, the Register() method registers the dependencies and the SendControlMessage() method checks whether the transferred machine exists in the dictionary, if so we display the corresponding message.

Let’s see how the Machine class looks like.

Very similar to the Participant class, only the SendControlMessage() method is defined here, it is implemented in the classes responsible for the machine types that are below.

It can be seen that in these classes we call the SendControlMessage() method defined in the ControlTower class to which we pass the name of the machine and check in it whether such a machine is registered.

And the client:

Result

 

Relations with other design patterns

  • The mediator is similar to the facade in that it simplifies the existing functionality, but the difference is that the Mediator only simplifies the communication between classes and the facade creates an interface, thanks to which it will simply be easier to use existing functionalities.

 

Summary

That’s all about Mediator 🙂.

Link to github with the whole code from this article: https://github.com/Slaw145/MediatorTutorial

This content also you can find on my steemit blog https://steemit.com/design-patterns/@slawas/design-patterns-mediator

And on medium: https://medium.com/@sawomirkowalski/design-patterns-mediator-84b4a56c6d61

In the next article, we will talk about the Template Method pattern.

As a standard, I remind you about the newsletter, which I send notifications about new entries and additional information about the IT world in general.🙂

And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂

– site on fb: Devman.pl-Slawomir Kowalski

– group on fb: DevmanCommunity

Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.

Illustrations, pictures and diagrams are from: https://sourcemaking.com/design_patterns/mediator

 
If that post was useful for you share it with your friends :)

Post a comment

Be first!

avatar
  Subscribe  
Notify about