This is the third post in the Structural Design Patterns series and in this post, we will discuss the Facade Design Pattern and its implementation using the C# programming language.
The Facade Design Pattern provides a simplified single interface for a set of interfaces that represent different functionalities. The Facade Design Pattern falls into the Structural Pattern category as defined by the Gang of Four (GoF). If you are new to design patterns, I would highly recommend you to read the introductory post “Introduction to Design Patterns“
What is Facade Design Pattern?
A Facade Design Pattern is used to provide a single unified client-facing interface to a complex system. Here the complex system can be composed of multiple libraries, frameworks having different classes representing different functionalities.
The unified single interface is called the facade and it exposes only those limited functionalities that the client is interested in. The implementation details of the exposed functionalities are also hidden from the client. All the other functionalities of the complex system are hidden in the background, thus making it easier for the client to use the service without worrying about the whole complex system and the different functions it has to offer.
The Facade accepts all the incoming client’s requests and invokes the required function or functions from different parts of the system and returns the appropriate response to the client.
When to consider Facade Design Pattern
Here are the few scenarios when we can consider the Facade Design Pattern
- When there is a need to hide the complexities of a large system having multiple classes offering interdependent functionalities.
- When there is a requirement that a client needs only a few selected functionalities from an interdependent subsystem.
- When a simpler easy to use wrapper class is required.
- When a single functionality is required to achieve an interdependent solution, and all the operations need to be performed on behalf of the client by hiding the implementation details.
- When there is a need to define an entry point to subsystems, in order to decouple the code.
Facade Design Pattern – UML
Assuming the below given UML represents a complex system that composes of multiple Subsystems, having multiple classes in it which offer different functionalities.
The major classes and Subsystems participating in the UML are as follows:
- Subsystem: A Subsystem maybe a library or framework offering a set of related functionalities. Here all the Subsystems together create a complex system with a multitude of combined functionalities. The client may not be interested in using all the functionalities offered by the complete system.
- Facade: The Facade class offers only those functionality the client is interested in, for this here the Facade class offers a new API (DoSomething()), which will serve the needful for the client. The DoSomething() can initialize and call multiple classes from different subsystems in order to serve the client’s requirement. All these implementation details are hidden from the client.
- Client: This is the consumer of the service or a set of services from the complex system has to offer.
C# Implementation
Let us build a simple console application to implement the Facade Pattern using the below-given requirement.
Requirement Description
Let us assume we have an existing three database services which offer two methods for adding and updating items into the database (data is not being actually saved to the database just a mockup). They are as follows:
- EmployeeDbService: The class exposes two methods that allow to add a new Employee and Update the same in the database.
- ProjectDbService: This class exposes two methods that allow to add and update Project details for an employee.
- SalaryDbService: This class exposes two methods that allow to add and update the Salary details of an employee.
The above-mentioned database services are individual services and can be called independent of each other.
The client is not interested in calling these individual services instead it wants to have just two methods.
- When a new employee is added, related project and salary details should also be created in the database.
- A single method should be exposed to update employee, project, and salary details.
Let us build the solution for the client using an Employee Facade, the implementation is as follow:
Requirement Implementation in C#
The artifacts of the solutions are as follows:
1. Employee.cs: This is a model class that represents an Employee.
/// <summary> /// This is a model class that represents an Employee /// </summary> public class Employee { Random random = new Random(); public Employee() { Id = random.Next(1111, 999999); } public int Id { get; private set; } public string FirstName { get; set; } public string LastName { get; set; } }
2. Project.cs: This is a model class that represents a Project in an organization
/// <summary> /// This is a model class that represent a Project in an organization /// </summary> public class Project { public int EmployeeId { get; set; } public string Department { get; set; } }
3. Salary.cs: This is a model class that represents a Salary of an employee.
/// <summary> /// This is a model class that represents a Salary of an employee /// </summary> public class Salary { public int EmployeeId { get; set; } public decimal Basic { get; set; } public decimal Incentives { get; set; } }
4. EmployeeDbService: This is an Employee database service that has two methods to Add and Update Employee details to the database.
/// <summary> /// This is a Employee database service that have two method to Add and Update Employee details to the database /// </summary> public class EmployeeDbService { public int AddEmployee(Employee employee) { Console.WriteLine($"[New Employee] - Id# [{employee.Id}] FirstName# {employee.FirstName} LastName# {employee.LastName} added to the database"); return employee.Id; } public void UpdateEmployeeDetails(Employee employee) { Console.WriteLine($"[Update Employee] - Id# [{employee.Id}] FirstName# {employee.FirstName} LastName# {employee.LastName} added to the database"); } }
5. ProjectDbService: This is the Project Database Service that Adds and Updates the project details of an employee in the database.
/// <summary> /// This is the Project Database Service that Adds and Updates project details of an employee in the database /// </summary> public class ProjectDbService { public void AddProjectDetails(int employeeId) { Project project = new Project(); project.EmployeeId = employeeId; project.Department = "NO-DEPARTMENT"; Console.WriteLine($"EmployeeId# [{employeeId}] allocated to [{project.Department}] department"); } public void UpdateProjectDetails(Project project) { Console.WriteLine($"[Updated] EmployeeId# [{project.EmployeeId}] allocated to [{project.Department}] department"); } }
6. SalaryDbService: This is the Salary Database Service, that Adds and Update the Salary details of an employee in the database.
/// <summary> /// This is the Salary Database Service, that Adds and Update Salary details of an employee in the database /// </summary> public class SalaryDbService { public void AddSalaryDetails(int employeeId) { Salary salary = new Salary(); salary.EmployeeId = employeeId; salary.Basic = 56543; salary.Incentives = 45656; Console.WriteLine($"Salary for EmployeeId# [{employeeId}] - Basic: {salary.Basic} Incentives: {salary.Incentives} added to the database"); } public void UpdateSalaryDetails(Salary salary) { Console.WriteLine($"Salary for EmployeeId# [{salary.EmployeeId}] - Basic: {salary.Basic} Incentives: {salary.Incentives} updated to the database"); } }
7. EmployeeFacade: This is the Facade class that combines all the three database services and provides an APIs AddNewEmployee and UpdateEmployee as per Client’s requirement and hide the implementation details from the client that it is calling all the related service to fulfill the client’s requirement
/// <summary> /// This is the Facade class that combines all the three database services and provides a /// APIs AddNewEmployee and UpdateEmployee as per Client's requirement and hide the implementation details from the client /// that it is calling all the related service to fulfill the client's requirement /// </summary> public class EmployeeFacade { private EmployeeDbService employeeDbService; private ProjectDbService projectDbService; private SalaryDbService salaryDbService; public EmployeeFacade() { employeeDbService = new EmployeeDbService(); projectDbService = new ProjectDbService(); salaryDbService = new SalaryDbService(); } public int AddNewEmployee(Employee employee) { var employeeId = employeeDbService.AddEmployee(employee); salaryDbService.AddSalaryDetails(employeeId); projectDbService.AddProjectDetails(employeeId); return employeeId; } public void UpdateEmployee(Employee employee, Salary salary, Project project) { employeeDbService.UpdateEmployeeDetails(employee); salaryDbService.UpdateSalaryDetails(salary); projectDbService.UpdateProjectDetails(project); } }
8. Client: This is the client that knows nothing about how the Facade manages to call the internal function to save and update Salary and Project details about an Employee and just calls the Facade method to Add and Update employee details.
class Client { static void Main(string[] args) { var facade = new EmployeeFacade(); var employee = new Employee { FirstName = "John", LastName = "Doe" }; facade.AddNewEmployee(employee); Console.WriteLine(); employee.FirstName = "Jonny"; var updatedSalary = new Salary { EmployeeId = employee.Id, Basic = 999999, Incentives = 22222 }; var updatedProject = new Project { EmployeeId = employee.Id, Department = "Finance" }; facade.UpdateEmployee(employee, updatedSalary, updatedProject); } }
Application Output
The output of the application is as follows:
Source Code
Please find the source code at GitHub: https://github.com/technicalbundle/FacadePattern
Advantages of Facade Design Pattern
Few of the advantage of the Facade Design Pattern are as follows:
- The pattern allows defining a simple interface that hides the complexity of the interdependencies of the subsystems.
- The Facade interface decouples the code, making it easier to add enhancements later on.
- The pattern allows defining methods specific to clients’ requirements without overwhelming them with all the available options the system has to offer.
- The pattern helps to improve the code readability and usability by hiding the subsystem’s complexity behind the single Facade class.
Disadvantages of Facade Design Pattern
Few of the disadvantages of the Facade Design Patterns are as follows:
- The Facade Design Pattern introduces an additional layer between the client and the subsystem, this contributes to the code complexity.
- Additional request forwarding is introduced between the client and subsystem functionality.
- The Pattern creates a dependency between various subsystems as various methods are called from them to serve the client.
- The client’s specific API’s need to be introduced in the Facade class, this requires additional maintenance.
Conclusion
In this blog post, we try to learn about the Facade Design Pattern, where it is applicable along with its advantages and disadvantages. Overall, it is a great pattern and comes really handy when the system begins to evolve larger and grows more complex over time.
I hope you found this post helpful. Thanks for visiting. Cheers!!!
[Further Readings: Proxy Design Pattern in C# | SQLite Studio to manage SQLite databases | Adapter Design Pattern in C# | How to use Blazor EditForm for Model Validation | How to add a new profile in Windows Terminal | How to easily Customize Global Settings in Windows Terminal | How to add Git Bash to Windows Terminal Application | How to customize Windows Terminal Application | How to customize Windows Terminal Key Bindings | How to Install Windows Terminal in Windows 10 | Important Debugging Shortcuts of Visual Studio 2019 | How to publish a Blazor Server Application to IIS ]