Design Patterns - Facade
In our previous blog of the design pattern series, we had discussed the decorator design pattern, which falls under the category of structural design patterns. Today, we will explore another design pattern from the same category called Facade Design Pattern.
Table of contents
- Introduction to Facade design pattern
- Implementation of Facade design pattern
- Conclusion
Introduction to Facade design pattern
A Facade is a structural design pattern specifically used when we need to transform complex functionalities into simple ones. In our previous blogs, you would have come across the Builder design pattern. The Facade design pattern is more or less similar to the Builder’s core idea - to create an object, a step-by-step approach is followed rather than doing it in a single step.
A Facade is used to hide the complex code involved in achieving a particular functionality. It exposes only a simple piece of code. In summary, the Builder is used to create objects, while a Facade is used to simplify complex functionalities.
Let us simplify Facade a little more. Facade provides a simple interface that hides the complex functionality behind it. It makes the code easier to understand as it provides a single entry to achieve the desired functionality (within which the complex functionality is called). The Facade pattern is particularly more effective when there are multiple dependencies between the client and independent classes.
Implementation of Facade design pattern
The Facade design pattern mainly consists of
- One or More SubClasses
- Facade class
- Client
One or more subclasses corresponds to the functionalities that are being achieved in multiple classes, which, in turn, are required to achieve the final requirement. These are the classes that are part of the complex system.
A Facade class is a wrapper that communicates with the subclasses/subsystems and gets the requirement achieved.
The client is an important part of the code that consumes the Facade class.
using System;
namespace PARTECH_Facade
{
internal class Program
{
static void Main(string[] args)
{
var facade = new Facade();
facade.CallAction1();
facade.CallAction2();
Console.ReadLine();
}
}
public class SubSystemA
{
public void Action1()
{
Console.WriteLine("SubSystem - A : Action 1");
}
public void Action2()
{
Console.WriteLine("SubSystem - A : Action 2");
}
}
public class SubSystemB
{
public void Action1()
{
Console.WriteLine("SubSystem - B : Action 1");
}
public void Action2()
{
Console.WriteLine("SubSystem - B : Action 2");
}
}
public class SubSystemC
{
public void Action1()
{
Console.WriteLine("SubSystem - C : Action 1");
}
public void Action2()
{
Console.WriteLine("SubSystem - C : Action 2");
}
}
public class Facade
{
SubSystemA a = new SubSystemA();
SubSystemB b = new SubSystemB();
SubSystemC c = new SubSystemC();
public void CallAction1()
{
a.Action1();
b.Action1();
c.Action1();
}
public void CallAction2()
{
a.Action2();
b.Action2();
c.Action2();
}
}
}
Here, Classes Subsystems A, B, and C are the subclasses that are part of the complex system. Each of them has two methods, Action1 and Action2. For easy understanding, logging is being done inside them.
Inside the Facade class, an object for Subclasses is created, i.e., for Subsystems A, B, and C. It has two methods that are only exposed to the client hiding the complex system calls behind it. The client is the Main class here, where the object for the facade is created, and the required methods are called.
Let’s implement the Facade design pattern for a real-life scenario and understand it better.
Consider a bank that lets you open an account through its web application. Since this is a bank, there are multiple processes and steps involved in opening an account. Similarly, there will be different processes for opening major and minor accounts. But, as an end-user or an employee of the bank, you will not want this process to be too cumbersome. It should be simple to understand, and the desired result should be achieved without any hassle. Let us implement the code for this scenario using the Facade design pattern.
using System;
namespace PARTECH_Facade
{
internal class Program
{
static void Main(string[] args)
{
IAccountCreation accountCreation = new AccountCreation();
Console.WriteLine("Enter the age to create account:");
string inputData = Console.ReadLine();
while (inputData != null)
{
int.TryParse(inputData, out int age);
if (age >= 18)
accountCreation.CreateMajorAccount();
else
accountCreation.CreateMinorAccount();
Console.WriteLine();
Console.WriteLine("Enter the age to create account:");
inputData = Console.ReadLine();
}
}
}
public interface IAccountCreation
{
void CreateMajorAccount();
void CreateMinorAccount();
}
public class AccountCreation : IAccountCreation
{
TaxIdentifierNumber tinData = new TaxIdentifierNumber();
AccountDetails accountDetails = new AccountDetails();
Proof proofDetails = new Proof();
public void CreateMajorAccount()
{
tinData.LinkTINData();
accountDetails.SelfAccount();
proofDetails.SelfAttestedProof();
}
public void CreateMinorAccount()
{
tinData.LinkTINDataOfGuardian();
accountDetails.JointAccount();
proofDetails.GuardianAttestedProof();
}
}
public class TaxIdentifierNumber
{
public void LinkTINData()
{
Console.WriteLine("TIN Data Linked.");
}
public void LinkTINDataOfGuardian()
{
Console.WriteLine("Guardian TIN Data Linked.");
}
}
public class AccountDetails
{
public void SelfAccount()
{
Console.WriteLine("Self Account created");
}
public void JointAccount()
{
Console.WriteLine("Joint Account created");
}
}
public class Proof
{
public void SelfAttestedProof()
{
Console.WriteLine("Self Attested Proof accepted.");
}
public void GuardianAttestedProof()
{
Console.WriteLine("Guardian self attested Proof accepted.");
}
}
}
In the above code,
Classes ‘TaxIdentifierNumber’ and ‘AccountDetails’ are the subsystems.
AccountCreation is the Facade class, while IAccountCreation is the interface used for it.
If you observe the code, the account creation class exposes only two methods outside; one for creating an account for major (CreateMajorAccount) and another for minor (CreateMinorAccount). But, objects for both the classes (TaxIdentifierNumber and AccountDetails) are created globally within the Facade class. Based on the requirement, the corresponding methods inside TaxIdentifierNumber and AccountDetails classes are called.
This explains the use of a Facade where only the essential details are exposed to the client while the complex system/calls are hidden underneath it.
On executing the above code, the below result will be displayed -
The above code provides an option to enter the age of the account holder. Based on the input provided, the corresponding account creation method is called, which then internally calls the sequence of steps that are involved in creating an account.
Conclusion
And that’s what a Facade Structural design pattern is all about. In this post, we have also seen how to implement it in a real-world scenario. Stay tuned for the next blog on the Design Patterns series.