Facade design pattern is a structural design pattern and it's used widely. The aim of this design pattern is to provide a simple interface to the client for a complex underlying system. So, facade means face of the building. This design pattern hides all complexities of the system and just displays a simple face. Very common example could be URL interface of a browser, which hides all complexities behind and only accepts a URL which user intends to browse. Another common example could be withdrawal / deposit of money from banking system via ATM.
To withdraw money we need following steps to achieve successfully:
1. Validate card / account number
2. Validate pin
3. In case of withdrawal check account balance and allow / disallow withdrawal
4. Follow steps 1 & 2 for account deposit (Steps 3 not needed).
5. Finally show the balance.
Code Example:
<Code>
File: WelcomeBank.h
#pragma once
#include <fmt/format.h>
class WelcomeBank{
public:
// ctor...
WelcomeBank(){
fmt::print("{}\n", "Welcome to ABC Bank");
}
};
File: AccountNumberCheck.h
class AccountNumberCheck {
private:
unsigned int _acctNumber = 12345678;
public:
unsigned int getAccountNumber() { return _acctNumber; }
bool isAccountActive(unsigned int accountNumber)
{
if(getAccountNumber() == accountNumber) return true;
else return false;
}
};
File: SecurityCodeCheck.h
#pragma once
class SecurityCodeCheck{
private:
unsigned int _securityCode = 1234;
public:
unsigned int getSecurityCode() { return _securityCode; }
bool isCodeCorrect(unsigned int securityCodeToCheck)
{
if(getSecurityCode() == securityCodeToCheck)
return true;
else
return false;
}
};
File: FundsCheck.h
#pragma once
#include <fmt/format.h>
class FundsCheck {
double cashInAccount = 1000.00;
void decreaseCashInAccount(double cashWithDrawn) {
cashInAccount -= cashWithDrawn;
}
void increaseCashInAccount(double cashDeposited) {
cashInAccount += cashDeposited;
}
public:
double getCashInAccount() {
return cashInAccount;
}
bool haveEnoughMoney(double cashWithDrawal) {
if(cashWithDrawal > getCashInAccount()) {
fmt::print("Error: Don't have enough balanace!\n");
fmt::print("Current Balance: {}\n", getCashInAccount());
return false;
}
else {
decreaseCashInAccount(cashWithDrawal);
fmt::print("Withdrawal complete, New Balance is: {}\n", getCashInAccount());
return true;
}
}
void makeDeposits(double cashToDeposit){
increaseCashInAccount(cashToDeposit);
fmt::print("Deposit complete, new balance is: {}\n", getCashInAccount());
}
};
File: BankAccountFacade.h
/* This is our facade implementation */
#include "AccountNumberCheck.h"
#include "FundsCheck.h"
#include "SecurityCodeCheck.h"
#include "WelcomeBank.h"
class BankAccountFacade{
private:
unsigned int _accountNumber;
unsigned int _securityCode;
AccountNumberCheck accCheker;
SecurityCodeCheck codeChecker;
FundsCheck fundCheker;
public:
BankAccountFacade(int accNum, int secCode) :
_accountNumber(accNum),
_securityCode(secCode) {}
unsigned int getAccountNumber() { return _accountNumber; }
unsigned int getSecurityCode() { return _securityCode; }
void withdrawCash(double cashToGet) {
WelcomeBank bankGreet;
if(accCheker.isAccountActive(getAccountNumber()) &&
codeChecker.isCodeCorrect(getSecurityCode()) &&
fundCheker.haveEnoughMoney(cashToGet)) {
fmt::print("Transaction complete\n");
}
else
fmt::print("Transaction failed\n");
}
void depositCash(double cashToDeposit) {
WelcomeBank bankGreet;
if(accCheker.isAccountActive(getAccountNumber()) &&
codeChecker.isCodeCorrect(getSecurityCode())) {
fundCheker.makeDeposits(cashToDeposit);
fmt::print("Transaction complete\n");
}
else
fmt::print("Transaction failed\n");
}
};
// This part contains our client code
File: example.cpp
#include "BankAccountFacade.h"
int main()
{
BankAccountFacade accessingBank(12345678, 1234);
accessingBank.withdrawCash(50.00);
accessingBank.withdrawCash(900.00);
accessingBank.depositCash(50.00);
return 0;
}
</Code>
Demo (Compiler Explorer code)
Credit: Design Patterns: Elements of Reusable Object-Oriented Software (by GoF)
Comments