Facade design pattern for beginners.

Background – 

Mask is one of the synonym of facade in the English language. Facade design pattern is actually doing the same things, that its English meaning tells. It wears a mask of simplicity to hide the complexity of a large and complex subsystems.

It makes an easy to use interface. Many times we deal with legacy library along with some modern and complex libraries in our project. Dealing with all of them individually is not an easy job from the maintenance point of view. To reduce the complicity, we can use the facade design pattern. Create a lightweight interface which will talk to different libraries. You just have to call that interface without bothering how it will work internally.

For a small application, having few classes, and 1 or 2 libraries is not the right candidate for facade. It is for large and complex system.

About facade design pattern –

Facade doesn’t add any new functionality to the existing system. It just remove complexities. The only problem with this approach is when the facade is the single point of connect. Then it will reduce the system’s strength. Developer will only be able to use functionality exposes by facade nothing else, even though libraries may offer more functionality, that is the biggest drawback.




Thanks, Abhishek, for asking this question – “What is the difference between façade and front controller”? It helped me looking at façade from that angle. I am listing down few easy differences. Hope that will answer your question :).

Deference between facade and front controller-

  1. The front controller is a singleton, and it controls the whole system. You can assume it as a bottleneck point of the entire system. Other side, the facade act as an interface which hides complexities and facilitates a wrapper, which is simple to use and easy to understand.
  2. Ideally, front controller and facade, both shall not have any business logic in it. 
    • Front controller can have a decision making logic based on input. It will assign work, and if the application is small, it can have business logic in it; which take end to end responsibility of work assignment. For large applications, we use command design patterns, along with the front controller. 
    • Facade has to be thin and without business logic. As it does not have to do any decision making.
  3. Front controller is an architectural pattern, whereas facade is structural design pattern (low level).
  4. Front controller is to mediate, view and control entity of MVC architecture. Whereas facade is just a wrapper which will reduce the underlying complexities.

UML Structure  - 




Example -



CPP code -


/**************************************************************************************
/* Façade design pattern - 
/* There are N number of banks and 1 person can hold N number of account in any bank.
/* create a login in each bank portal and do transaction from there is a pain. Think 
/* of a common payment gateway for you, where you just tell detect money from X account
/* for Y bill payment, no need to login in any specific portal and you will manage all 
/* from one place. 
***************************************************************************************/

#include<iostream>
#include<map>
#include<vector>
#include<string>
using namespace std;
struct AccountInfo
{
    vector<string> m_accountNumber;
    string m_cardNumber;
    string m_password;
};
//*************************************************************************************
// Class HDFCBankAsExample a dummy class to explain façade.
class HDFCBankAsExample
{
    public:
        // there will be many functions but I am demonstrating only payBill to understand façade.
        void payBill(string to, string name, string accountNumber, 
                    string cardNumber, string password, int amount)
        {
            cout<< "HDFC -> your transaction from account # "<< accountNumber << " to pay bill in favour of " << to;
            cout<< " , amount "<< amount << " has been successfully deducted"<<endl;
        }
};
//*************************************************************************************
// Class SBIBankAsExample a dummy class to explain façade.
class SBIBankAsExample
{
    public:
        // there will be many functions but I am demonstrating only payBill to understand façade.
        void payBill(string to, string name, string accountNumber, 
                    string cardNumber, string password, int amount)
        {
            cout<< "SBI -> your transaction from account # "<< accountNumber << " to pay bill in favour of " << to;
            cout<< " , amount "<< amount << " has been successfully deducted"<<endl;
        }
};
//*************************************************************************************
// Class ICICIBankAsExample a dummy class to explain façade.
class ICICIBankAsExample
{
    public:
        // there will be many functions but I am demonstrating only payBill to understand façade.
        void payBill(string to, string name, string accountNumber, 
                    string cardNumber, string password, int amount)
        {
            cout<< "ICICI - > your transaction from account # "<< accountNumber << " to pay bill in favour of " << to;
            cout<< " , amount "<< amount << " has been successfully deducted"<<endl;
        }
};

//*************************************************************************************
// Class  Common Payment Gateway for all banks 
class CommonPaymentGateway
{
    public:
        CommonPaymentGateway(string name, string accountNumber, 
                             string cardNumber, string password)
        {
            AccountInfo accountInfo;
            accountInfo.m_accountNumber.push_back(accountNumber);
            accountInfo.m_cardNumber = cardNumber;
            accountInfo.m_password = password;
            m_dictionary.insert(pair<string, AccountInfo> (name, accountInfo));
        }
        void addAccountNumber(string name, string accountNumber)
        {
            if(m_dictionary.find(name) != m_dictionary.end())
            {
                m_dictionary.find(name)->second.m_accountNumber.push_back(accountNumber);
            }
            else 
            {
                cout<< "Name doesn't exist "<<endl;
            }
        }
        void payBill(string to, string name, string accountNumber, int amount)
        {
            if(m_dictionary.find(name) != m_dictionary.end())
            {
                AccountInfo temp = m_dictionary.find(name)->second;
                if(accountNumber.substr(0, 2) == "55")
                {
                    //HDFC
                    if(findAccountDetails(temp,accountNumber))
                    {
                        m_HDFCBankAsExample.payBill(to,name,accountNumber,temp.m_cardNumber,
                                                    temp.m_password,amount);
                    }
                    else
                    {
                        cout<< "you have entered wrong account number" << endl;
                    }
                }
                if(accountNumber.substr(0, 2) == "22")
                {
                    //SBI
                    if(findAccountDetails(temp,accountNumber))
                    {
                        m_SBIBankAsExample.payBill(to,name,accountNumber,temp.m_cardNumber,
                                                    temp.m_password,amount);
                    }
                    else
                    {
                        cout<< "you have entered wrong account number" << endl;
                    }
                }
                if(accountNumber.substr(0, 2) == "59")
                {
                    //ICIC
                    if(findAccountDetails(temp,accountNumber))
                    {
                        m_ICICIBankAsExample.payBill(to,name,accountNumber,temp.m_cardNumber,
                                                    temp.m_password,amount);
                    }
                    else
                    {
                        cout<< "you have entered wrong account number" << endl;
                    }
                }
                // we can add as many as we want .................
            }
            else 
            {
                cout<< "Name doesn't exist "<<endl;
            }
        }
        bool findAccountDetails(AccountInfo& accountInfo, string& accountNumber)
        {
            for(int index = 0; index < accountInfo.m_accountNumber.size(); index++)
            {
                if(accountInfo.m_accountNumber[index] == accountNumber)
                {
                    return true;
                }
            }
            return false;
        }
    private:
        map <string,AccountInfo> m_dictionary;
        HDFCBankAsExample m_HDFCBankAsExample;
        SBIBankAsExample m_SBIBankAsExample;
        ICICIBankAsExample m_ICICIBankAsExample;
};
/*
#######################################################################################
#########  __  __       _        ######################################################
######### |  \/  | __ _(_)_ __   ######################################################
######### | |\/| |/ _` | | '_ \  ######################################################
######### | |  | | (_| | | | | | ######################################################
######### |_|  |_|\__,_|_|_| |_| ######################################################
#######################################################################################
*/
int main(int argc, char **argv)
{
    CommonPaymentGateway commonPaymentGatewayObject01("SomeName", "550000551",
                                "1234-5678-9101-1123","mypassword");
    commonPaymentGatewayObject01.addAccountNumber("SomeName", "220000551");
    commonPaymentGatewayObject01.addAccountNumber("SomeName", "590000551");
    
    commonPaymentGatewayObject01.payBill("internet","SomeName","550000551",1500);
    commonPaymentGatewayObject01.payBill("HomeLone","SomeName","220000551",15000);
    commonPaymentGatewayObject01.payBill("MobileBill","SomeName","590000551",500);
    return 0;
}

///////////////////////////////////////////////////////////////////-------------OutPut
/*
$ ./a.exe
HDFC -> your transaction from account # 550000551 to pay bill in favour of internet , amount 1500 has been successfully deducted
SBI -> your transaction from account # 220000551 to pay bill in favour of HomeLone , amount 15000 has been successfully deducted
ICICI - > your transaction from account # 590000551 to pay bill in favour of MobileBill , amount 500 has been successfully deducted
*/



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.