Facade Pattern in C#

Hello, fellow C# developers! In this post, I’m going to introduce you to one of the most useful and elegant design patterns: the Facade pattern. If you have ever worked with a complex system that has multiple subsystems, libraries, or frameworks, you know how hard it can be to understand and use them. Sometimes, you just need a simple and unified interface that hides the complexity and provides only the functionality that you need. That’s where the Facade pattern comes in handy. šŸ˜Ž

What is the Facade pattern? šŸ¤”

According to the Gang of Four definition, the Facade pattern is a structural design pattern that provides a simplified interface to a set of interfaces in a subsystem. It defines a higher-level interface that makes the subsystem easier to use.

The Facade pattern involves a single wrapper class that contains a set of members required by the client. These members access the system on behalf of the facade client and hide the implementation details. The Facade pattern helps decrease the overall complexity of the application and move unwanted dependencies to one place.

The client interacts with the facade class, which delegates the requests to the appropriate subsystem classes. The subsystem classes implement the subsystem functionality and handle the work assigned by the facade class. The subsystem classes have no knowledge of the facade and keep no reference to it.

Why use the Facade pattern? šŸ™Œ

The Facade pattern has many benefits, such as:

  • It reduces coupling between the client and the subsystems by providing a single point of contact.
  • It simplifies the usage of complex systems by hiding their details and providing only relevant functionality.
  • It promotes modularity and maintainability by allowing changes in subsystems without affecting clients.
  • It enhances testability by allowing easier testing of subsystems through the facade interface.

How to implement the Facade pattern in C#? šŸ’»

Let’s see an example of how to implement the Facade pattern in C#. Suppose we have a finance application that uses various subsystems such as bank, credit, and loan. Each subsystem has its own interface and logic. To apply for a mortgage, we need to interact with all these subsystems and check various conditions. This can be tedious and error-prone. To simplify this process, we can create a facade class that provides a unified interface for applying for a mortgage.

First, let’s define some classes that represent our customers and our subsystems:


// The 'Customer' class
public class Customer
{
// Customer properties
public string Name { get; set; }
public double Balance { get; set; }
public int CreditScore { get; set; }
public bool HasBadLoans { get; set; }

// Customer constructor
public Customer(string name, double balance, int creditScore, bool hasBadLoans)
{
Name = name;
Balance = balance;
CreditScore = creditScore;
HasBadLoans = hasBadLoans;
}
}
// The 'Subsystem ClassA' class
public class Bank
{
// Check if the customer has sufficient balance in the bank account
public bool HasSufficientBalance(Customer customer, double amount)
{
return customer.Balance >= amount;
}
}
// The 'Subsystem ClassB' class
public class Credit
{
// Check if the customer has a good credit score
public bool HasGoodCredit(Customer customer)
{
return customer.CreditScore >= 700;
}
}
// The 'Subsystem ClassC' class
public class Loan
{
// Check if the customer has no bad loans in the past
public bool HasNoBadLoans(Customer customer)
{
return !customer.HasBadLoans;
}
}


Next, let’s create our facade class that provides a simplified interface for applying for a mortgage:


// The 'Facade' class
public class MortgageApplication
{
private readonly Bank _bank;
private readonly Credit _credit;
private readonly Loan _loan;

public MortgageApplication()
{
_bank = new Bank();
_credit = new Credit();
_loan = new Loan();
}

// The simplified interface for applying for a mortgage
public bool ApplyForMortgage(Customer customer, double amount)
{
Console.WriteLine($"{customer.Name} applies for {amount:C} mortgage\n");

bool eligible = true;

// Check bank account balance
if (!_bank.HasSufficientBalance(customer, amount))
{
eligible = false;
Console.WriteLine("Bank: Insufficient balance");
}

// Check credit score
if (!_credit.HasGoodCredit(customer))
{
eligible = false;
Console.WriteLine("Credit: Poor credit score");
}

// Check loan history
if (!_loan.HasNoBadLoans(customer))
{
eligible = false;
Console.WriteLine("Loan: Bad loan history");
}

return eligible;
}
}


As you can see, the facade class has a constructor that initializes the subsystem objects and a method that performs all the necessary checks for applying for a mortgage. The client only needs to call this method with the customer and amount parameters and get a boolean result indicating whether they are eligible or not.

Finally, let’s see how the client can use the facade class:

// The 'Client' class
public class Client
{
public static void Main(string[] args)
{
// Create some customers
Customer alice = new Customer("Alice", 10000, 700, false);
Customer bob = new Customer("Bob", 5000, 600, true);
Customer charlie = new Customer("Charlie", 15000, 800, false);

// Create a mortgage application facade
MortgageApplication mortgageApplication = new MortgageApplication();

// Try to apply for mortgages
double amount = 12000;

bool aliceResult = mortgageApplication.ApplyForMortgage(alice, amount);
Console.WriteLine($"Alice has been {(aliceResult ? "Approved" : "Rejected")}\n");

bool bobResult = mortgageApplication.ApplyForMortgage(bob, amount);
Console.WriteLine($"Bob has been {(bobResult ? "Approved" : "Rejected")}\n");

bool charlieResult = mortgageApplication.ApplyForMortgage(charlie, amount);
Console.WriteLine($"Charlie has been {(charlieResult ? "Approved" : "Rejected")}\n");

// Wait for user
Console.ReadKey();
}
}


The output is:

Alice applies for $12,000.00 mortgage

Bank: Insufficient balance
Alice has been Rejected

Bob applies for $12,000.00 mortgage

Bank: Insufficient balance
Credit: Poor credit score
Loan: Bad loan history
Bob has been Rejected

Charlie applies for $12,000.00 mortgage

Charlie has been Approved

As you can see, the client code is much simpler and cleaner than if it had to interact with each subsystem directly. The facade class encapsulates all the complexity and provides a user-friendly interface.

Conclusion šŸŽ‰

The Facade pattern is a great way to simplify the usage of complex systems by providing a unified interface that hides the details and provides only the functionality that you need. It reduces coupling, enhances modularity, and improves testability. It is widely used in many applications and frameworks that deal with multiple subsystems or libraries.

I hope you enjoyed this post and learned something new. If you want to learn more about the Facade pattern and other design patterns in C#, I recommend you check out these resources:


You can find the code examples here: source code

Happy coding! 😊

Comments

Popular posts from this blog

Which GOF patterns are good for C#?

Proxy pattern in C#

Bridge pattern in C#