Chain of responsibility design pattern for beginner.
Problem statement –
Let’s not go into too much technicality for now and discuss
something more exciting “traveling.” Yes, we all love traveling and like
to visit new places. You must have noticed, your cell phone will be active
always wherever you go. No one can figure out that you are out of station. By just calling at your cell phone number. If you don’t wish to tell him/her (especially to
your manager) about your travel.
Your mobile will work seamlessly across the states. Yes, I am talking about the “mobile - roaming model.” The concept of location transparency will come into the picture. Please click this link if you don’t know about location transparency. It says that you have to make the system believe that moving objects are inside of local space.
Your mobile will work seamlessly across the states. Yes, I am talking about the “mobile - roaming model.” The concept of location transparency will come into the picture. Please click this link if you don’t know about location transparency. It says that you have to make the system believe that moving objects are inside of local space.
(Just an pictorial representation of moving different state of India)
Now let’s understand how it works. You are pointing to an
object which is moving. The only issue with this problem is how you will find the
address of a moving object.
To solve that problem, we use “naming servers.”
Naming
Server is nothing but the collection of key and value. Where the value is the address
of the moving object. So each and every state will maintain a VLR (visitor location register), which is nothing but a naming
server.
It works straightforwardly -
- If an object enters any state. Server will register its entry into VLR table.
- As soon as the object (mobile) goes out of state. The server will remove its entry from VLR table.
Now, how you will get the address of moving object is the
question? Think a little, you will get the answer. The only person who knows about the actual
address of moving object is that object itself. Resulting from that, the object has to send a request
to the VLR table each time (whenever it enters any new state). So that, naming server could able to maintain the
address list.
(States with VLR table)
Okay, we understand that your mobile will send the
address information to VLRs. But how your home network will come to know that, currently, you
are in which state? Or in other words, which state’s VLR table has your address?
Well, through the chain of responsibility design pattern, we can solve it.
The first call will go to your home network always. It will see your name has been removed from VLR table (if you are out of station). What to do next?
Your local network will send a request to
the neighbor state. It will see if it has an address in their VLR table. If it finds, then it will return address. And call will get connected. Otherwise, the request will go to the next neighbor
state, and a request will keep on going until it finds you in a full mobile network. If not found, it will prompt an error message saying that mobile is out of reach.
Why we need the chain of responsibility design pattern –
The chain of responsibility design pattern is a competitor of observer design pattern. Observer design pattern is
fast and quick as compare to chain of responsibility. Many times we prefer
using observer. But when the number of nodes (or say users) are very, very high, or say unlimited. Like mobile users - N number of operators can have M numbers of users. Where you have no idea how many of them
are exist. Then it is a good idea to use the chain of responsibility.
About chain of responsibility design pattern –
We can understand the chain of responsibility design’s behavior
very well through a standard practice of many programming language called
“exception handling.”
- We don’t know at which point exception will come.
- We have to go back to the same route from where it came.
- We also have no idea at which point we are handling thrown exception. If we reach to the very first point. from where the call originated and yet exception is not handled then we call it unhandled exception.
(Exception handling -> control stack, and it has to come from same path)
UML Structure –
UML structure of the chain of responsibility. |
Example C ++
Exampe of the chain of responsibility design pattern (Click on picture to see zoom view). |
#include<iostream> #include<string> #include<map> using namespace std; bool trace = false; class VLR { public: VLR():m_next(NULL){} virtual void findLocation(string mobileNumber) = 0; virtual void moveToState(VLR* state, string mobileNumber) = 0; virtual void addMobile(string mobileNumber) = 0; protected: void setNextVLR(VLR* nextVLR) { m_next = nextVLR; } VLR* m_next; map<string, string> m_dictionary; }; class PrepaidVLR : public VLR { public: PrepaidVLR(string state): m_state(state) {} void addMobile(string mobileNumber) { if(trace == true) { cout<< "function addMobile with mobile number " <<mobileNumber << " and state "<< m_state<< endl; } m_dictionary.insert(pair<string,string>(mobileNumber,m_state)); } void findLocation(string mobileNumber) { if(trace == true) { cout<< "function findLocation with mobile number " <<mobileNumber<< endl; } map<string, string>::iterator it; it = m_dictionary.find(mobileNumber); if(it != m_dictionary.end()) { cout<< " " << it->second << endl; } else if(m_next != NULL) { m_next->findLocation(mobileNumber); } else { cout<<"wrong number"<<endl; } } void moveToState(VLR* state, string mobileNumber) { if(trace == true) { cout<< "function moveToState with state " <<m_state << " and mobile number " <<mobileNumber<< endl; } map<string, string>::iterator it; it = m_dictionary.find(mobileNumber); if(it != m_dictionary.end()) { if(trace == true) { cout<< " Erasing " << mobileNumber << "from DB" << endl; } m_dictionary.erase(it); } else { cout<< "mobile number " << mobileNumber << "is not exist under "<< m_state<< endl; return; } VLR::setNextVLR(state); m_next->addMobile(mobileNumber); } private: string m_state; }; /* ####################################################################################### ######### __ __ _ ###################################################### ######### | \/ | __ _(_)_ __ ###################################################### ######### | |\/| |/ _` | | '_ \ ###################################################### ######### | | | | (_| | | | | | ###################################################### ######### |_| |_|\__,_|_|_| |_| ###################################################### ####################################################################################### */ int main(int argc, char** argv) { trace = false; // for debug purpose. VLR* karnatakaVLRTable = new PrepaidVLR("Karnataka"); VLR* AndhraVLRTable = new PrepaidVLR("AndhraPradesh"); karnatakaVLRTable->addMobile("0000011"); karnatakaVLRTable->addMobile("0000012"); karnatakaVLRTable->addMobile("0000013"); karnatakaVLRTable->addMobile("0000014"); karnatakaVLRTable->addMobile("0000015"); AndhraVLRTable->addMobile("0000021"); AndhraVLRTable->addMobile("0000022"); AndhraVLRTable->addMobile("0000023"); AndhraVLRTable->addMobile("0000024"); AndhraVLRTable->addMobile("0000025"); cout<<"Location before moving to any other location "<<endl; karnatakaVLRTable->findLocation("0000014"); karnatakaVLRTable->moveToState(AndhraVLRTable, "0000014"); cout<<"Location after moving "<<endl; karnatakaVLRTable->findLocation("0000014"); return 0; } ///////////////////////////////////////////////////////////////////-------------OutPut /* $ ./a.exe Location before moving to any other location Karnataka Location after moving AndhraPradesh */
Thanks for reading it. To learn more about design patterns and basic design principles, please see my web page.
Comments
Post a Comment