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.


(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 -
  1. If an object enters any state. Server will register its entry into VLR table. 
  2. 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.

Okay, let me give you some practical aspects of the theory mentioned above. If you call someone and it gets connected without any beep sound. It means he/she is in his/her local network (here searching time is less as the system finds you in your home network). But sometimes you might have noticed, that you will get beep sound for a long time before your call gets connected (beep..beep..beep..). Actually, that is the time when your mobile network is searching your address through VLR, and you are not in your home state. Nowadays, software systems are fast, so they take lass time.

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.”
  1. We don’t know at which point exception will come.
  2. We have to go back to the same route from where it came.
  3. 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 –

the chain of responsibility Dp
UML structure of the chain of responsibility.

Example C ++


the chain of responsibility DP Ex
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

Popular posts from this blog

Non-virtual interface idiom (NVI)

Factory method design pattern for beginners.

Architectural patterns => Mud to structure => layers.