Mediator design pattern.

Background –

This design pattern shows a path and encourage us to find new problem statements (or opportunities) and a simple way to solve them. Solution of a huge problem, for example, how one node in an extensive system is going to talk to another node of the existing system?

Shadi.com may be a very classic example of mediator design pattern. Imagine a time before Shadi.com. Or any other matrimonial website. All parents, who desperately want their kids to get married, may like to talk to so many different people (or say, like to see many options). For example, if 100 people are of the same caste (of both gender). And can pair, then it will take factorial 100 (!100) combinations. They can pair ( plus they should be having the address of all other families, to connect and match pairs). Because it is a very tedious job. People quit searching after they reach 10 or 15 options. But they don’t want their kid to choose someone of his/her own choice; In India :P. Well, this is a different topic altogether!

The below diagram shows how bad an idea it is, for one node to communicate with other nodes in an extensive system without a mediator. Every node can talk to all other nodes in the big system.

But now Shadi.com is a mediator for all people to reach others. Happy parents :), and it will not take a headache to remember address of others, you just tell you want to talk to other nodes, and you will get all connect details, with very less effort.


Remember, in the old days, we all have one family member, who was very worried about your marriage (more than your direct parents). He used to show many options and keep pushing you marry this girl/boy. He was your mediator, that is how actually mediator works. Nowadays, Shadi.com and other matrimonial sites have become your new mediator.

So, the main job of the mediator is to establish a channel between two different objects, so that they can communicate.  

Now, remember one rule. If there are very few modules in your system. Let’s say 4 to 5. Then manager or front controller itself is enough to handle all communication logic. All system components can afford a code that will talk to all other components as it is a small system. But in real software product. You will have more modules, then it is not a good idea at all to have a logic inside all nodes to communicate to all other nodes. Or some n number of related nodes. Most of internet-related application will have a high number of connected nodes, and mediator reduces its complexity.

If you have a new requirement and have to add a new module, then imagine what all places you have to change the code? In all other existing related modules right (without mediator), but you can avoid it if you implement mediator design pattern in your product.
Now imagine a software solution where several modules are present. A vast project, handling all through one mediator is not a good idea. So actually we can have many mini mediator talking to a center mediator component. 

Remember one more important point, that in mediator, connections are bidirectional not like manager or front controller design, mediator and node both will be able to talk to each other without any restriction.



Our middleware software’s are mediators, CORBA is one of the classic example of middleware software. It reduces the complexity of communicating one node with another node in the software system.

Advantage –

It reduces complexity.

Disadvantage –

Single point of failure. If the mediator is buggy or crashed/down, then the whole system will go down.

UML representation -

Mediator DP
Structure of Mediator design pattern

Different components of UML structure -


  • Mediator - is an interface class. Which will give you interface through which you can communicate between two colleague objects.
  • ConcreteMediator - is an implementation class of Mediator interface. Where you will put the logic, that how two different colleague objects are going to communicate.
  • Colleague - is an interface class of your implementation module.
  • ConcreteColleague - is the real business logic implementation of your module. 

Example -

Mediator DP
Ex Mediator design pattern (Click on picture to see zoom view)


#include<iostream>
#include<string>
#include<memory>
using namespace std;

class MyBlog; // forward declaration.

class SomeGirl
{
private:
 weak_ptr<MyBlog> pMediator;
 string msg;

public:
 SomeGirl() {}
 void Receive(const string& InputMsg) const
 {
  cout << "SomeGirl received message - " << InputMsg << endl << endl;
 }
 // Send will be defined latter as it will use mediator pointer which has not been defined yet.
 void Send();
 ~SomeGirl()
 {
  cout << "Destructor of SomeGirl is called " << endl;
 }
 void SetMediator(shared_ptr<MyBlog> pBlog)
 {
  pMediator = pBlog;
 }
 void FormMassage(string WriteMsg)
 {
  msg = WriteMsg;
 }
};

class SomeBoy
{
private:
 weak_ptr<MyBlog> pMediator;
 string msg;
public:
 SomeBoy() {}
 void Receive(const string& InputMsg) const
 {
  cout << "message - " << InputMsg << endl;
 }
 // Send will be defined latter as it will use mediator pointer which has not been defined yet.
 void Send();
 ~SomeBoy()
 {
  cout << "Destructor of SomeBoy is called " << endl;
 }
 void SetMediator(shared_ptr<MyBlog> pBlog)
 {
  pMediator = pBlog;
 }
 void FormMassage(string WriteMsg)
 {
  msg = WriteMsg;
 }
};

class MyBlog
{
private:
 shared_ptr<SomeBoy> pBoy;
 shared_ptr<SomeGirl> pGirl;

public:
 MyBlog(shared_ptr<SomeBoy> boy, shared_ptr<SomeGirl> girl) :pBoy(boy), pGirl(girl)
 { }
 void SendToSomeBoy(const string& InputMsg) const
 {
  pBoy->Receive(InputMsg);
 }
 void SendToSomeGirl(const string& InputMsg) const
 {
  pGirl->Receive(InputMsg);
 }
 ~MyBlog()
 {
  cout << "Destructor of MyBlog is called " << endl;
 }
};

void SomeBoy::Send()
{
 pMediator.lock()->SendToSomeGirl(msg);
}
void SomeGirl::Send()
{
 pMediator.lock()->SendToSomeBoy(msg);
}
namespace Setup
{
 shared_ptr<SomeBoy> pBoy = make_shared<SomeBoy>();
 shared_ptr<SomeGirl> pGirl = make_shared<SomeGirl>();
 shared_ptr<MyBlog> pMediator = make_shared<MyBlog>(pBoy, pGirl);
 void Init()
 {
  pGirl->SetMediator(pMediator);
  pBoy->SetMediator(pMediator);
 }
}
namespace Run
{
 void Execute()
 {
  string str = "Happy new year 2016";
  Setup::pBoy->FormMassage(str);
  Setup::pBoy->Send();
 }
}
/*
#######################################################################################
#########  __  __       _        ######################################################
######### |  \/  | __ _(_)_ __   ######################################################
######### | |\/| |/ _` | | '_ \  ######################################################
######### | |  | | (_| | | | | | ######################################################
######### |_|  |_|\__,_|_|_| |_| ######################################################
#######################################################################################
*/
int main(int argc, char** argv)
{
 Setup::Init();
 Run::Execute();
 return 0;

}

///////////////////////////////////////////////////////////////////-------------OutPut
/*
$ ./a.exe
SomeGirl received message - Happy new year 2016

Destructor of MyBlog is called
Destructor of SomeGirl is called
Destructor of SomeBoy is called
*/

Thanks for reading it. To learn more about design patterns and basic design principles, please see my web page. You can also join me on FB or on G++. Please drop comments for any question related to this blog.

Comments

Popular posts from this blog

Non-virtual interface idiom (NVI)

Factory method design pattern for beginners.

Architectural patterns => Mud to structure => layers.