Facade Design Pattern Explained In-depth For C# Developers
The facade design pattern is a simple yet powerful and effective structural design pattern. The facade design pattern has helped me on many occasions, especially when dealing with legacy application code.
Let us have a look at the “Gang of Four” definition:
“Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.”
I want you to emphasize on the second sentence, and it tells us we need to create a new layer [ this could be a new class or an API ], which will sit on top of our existing low-level interface [that is existing classes or API ]. And should effectively hide the complexity of the current code for our client.
* You can think of a complex system as projects in a solution with hundreds of classes and thousands of methods which our client does not need to learn. Or large numbers of parameters that a class might need to instantiate and are irrelevant to our clients need, I can go on and on here.
Now taking a look at the first sentence, it tells us our facade layer should be the single source of truth to access the functionalities that the underlying subsystem is offering. In other words, it means our client will call the methods in the facade layer, which in turn will call the appropriate methods of the classes in the subsystem.
* Gang of four uses the term subsystem in the definition, and I think its an intelligent choice of word on their behave. Subsystem means a collection of specific components in the application the client needs to deal with to fulfill its requirements, e.g., Customer, Order, Sales, Suppliers, etc. It will be rare that we might need a facade layer over the complete system [An API Gateway over entire APIs of an application can be an exception to my argument here]. So our facade layer might only deal with a subsystem that consists of just customer and order.
Take a look at the following code. For simplicity, I have shown here two components CustomerServices and SalesService, which implements ICustomerServices and ISalesService, respectively. In this example, I have used two components with few methods, but in real life, there could be many more methods.
Now the following code block is our client, which is the main method, and it has these simple requirements first to get all active customers by region and second to get all sales by region and date range. Without the facade layer, our client will need to learn in detail about the behaviors provided by ICustomerServices and ISalesService Interface to complete its requirements.
I will now try to simplify the Interface that our client will have to deal with to fulfill its requirement by creating a facade. Here is the code block of the facade layer.
In the above code, I have created CustomerSalesFacade, which implements ICustomerSalesFacade. Our CustomerSalesFacade class uses composition and initializes its dependencies CustomerServices and SalesService in its constructor so that every time CustomerSalesFacade gets initialize, its dependencies also gets initialized.
For the first requirement, I have simplified the method signature and made the method name more verbose. For the second requirement method name and method signature is the same, however for both the cases now our client has to know about just two methods that it will be using. Also, I have added a new behavior APIAccessCounter, which is an analytics method to show you that the facade layer can also be used to add additional methods that otherwise would be difficult to add.
In the following code block, our client now has to deal with a much simpler interface.
* If you have read my previous article on The Adapter Design Pattern, Here is an essential difference between the two. The Facade Pattern Simplifies the interface for our client while the Adapter pattern changes the interface of an existing interface.
To summarize, the facade layer enables us to create a simpler interface for our client and filter out the complex interface of the underlying layer to fulfill the requirements. The facade layer can also be used to add additional functionalities.