Facade Design Pattern With Example

In this article, we will try to implement a Facade Design pattern using an example of a banking system that has different types of accounts like checking and savings.

Q. What is the Goal/Purpose of the Facade Pattern with analogy?

The goal is to provide a single simplified interface for client classes to interact with the sub-system while hiding complexity from the client side. In our example, we will be using the information hiding principle to prevent all client classes from seeing the account type objects in our simple banking system and how these accounts behave.

Q. What is Facade and why is it used?

Facade is simply a point of entry into any subsystem; e.g., a waiter at a restaurant while ordering food, an online shopping portal for ordering products, shipping, production etc.

  • Façade is a wrapper class that encapsulates the subsystem in order to hide the subsystem’s complexity.
  • This wrapper class allows the client class to interact with the subsystem through a façade.
  • It combines interface implementation by one or more classes, which then gets wrapped by the façade class.

Q. How would client code interact with the subsystem without a façade class for our simple banking system?

  • Without a facade class, the Customer class would contain instances of checking, savings, and investment classes.
  • This means the customer is responsible for properly instantiating each of these constituent classes and knows about all their different attributes and methods.
    Facade class

Q. How would client code interact with the subsystem with a façade class for our simple banking system?

  • We introduce the BankService class to act as a façade for the chequing, saving, and investment classes.
  • The customer class no longer needs to handle instantiation or deal with any of the complexities of financial management.
  • Since three different accounts, all implement the IAccount interface, bankservice class is effectively wrapping the account interfacing classes, and presenting a simpler front to them for the customer client class to use.
     IAccount interface

Q. How do we Implement a Facade Pattern for our Example?

Step 1. Implementing our BankService facade class which wraps the other classes that implement the interface.

public class BankService {
    private Dictionary<int, IAccount> bankAccounts;

    public BankService() {
        bankAccounts = new Dictionary<int, IAccount>();
    }

    public int createNewAccount(string type, BigInteger initAmount) {
        IAccount newAccount = null;

        switch (type) {
            case "chequing":
                newAccount = new Chequing(initAmount);
                break;
            case "saving":
                newAccount = new Saving(initAmount);
                break;
            case "investment":
                newAccount = new Investment(initAmount);
                break;
            default:
                Console.WriteLine("Invalid account type");
                break;
        }

        if (newAccount != null) {
            bankAccounts.Add(newAccount.getAccountNumber(), newAccount);
            return newAccount.getAccountNumber();
        }
        return -1;
    }

    public void transferMoney(int to, int from, BigInteger amount) {
        IAccount toAccount = GetAccount(bankAccounts, to);
        IAccount fromAccount = GetAccount(bankAccounts, from);

        if (toAccount != null && fromAccount != null) {
            fromAccount.transfer(toAccount, amount);
        } else {
            // we can inform user about failure either by throwing exception or sending error code.
        }
    }

    // we can replace below searching account code with any other efficient code as per requirement.
    private IAccount GetAccount(Dictionary<int, IAccount> bankAccounts, int to) {
        IAccount account = null;
        if (bankAccounts.TryGetValue(to, out account)) {
            return account;
        }
        return account;
    }
}

From the above code snippet we can observe.

  • Our BankService class is the facade class.
  • Its public methods are simple to use and show no hint of the underlying interface and implementing classes.
  • We set the access modifiers for each account to be private.

Step 2. Implementing Customer class which uses BankService facade class to access the subsystem.

public class Customer
{
    static void Main(string[] args)
    {
        BankService bankService = new BankService();
        int savingAccount = bankService.createNewAccount("saving", new BigInteger(500.00));
        int investmentAccount = bankService.createNewAccount("investment", new BigInteger(1000.00));
        bankService.transferMoney(savingAccount, investmentAccount, new BigInteger(300.00));
    }
}

From the above code snippet we can observe.

  • Client classes can access the functionalities of the different available accounts through the methods of the bank service class.
  • The bank service class will tell the client what type of actions it will allow the client to call upon and then will delegate that action to the appropriate account objects.
  • Now customer class does not need to worry about creating and managing its own accounts.
  • The customer simply needs to know about the bank services and the set of behaviors the bank service is capable of performing.

Q. Advantages of Facade Design Pattern?

  1. This pattern hides the complexity of a subsystem by encapsulating it behind a unifying wrapper called a Facade class.
  2. Removes the need for client classes to manage a subsystem on their own, resulting in less coupling between the subsystem and the client classes.
  3. Handles instantiation and redirection tasks to the appropriate class within the subsystem.
  4. Provides client classes with a simplified interface for the subsystem.
  5. Acts as a point of entry to a subsystem and does not add more functionality to the subsystem.