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.
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 -
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 -
#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
Post a Comment