The Facade Design Pattern
Introduction to the Facade Pattern
Have you ever heard of the Gang of Four Design Patterns? Well, the Gang of Four Design Patterns are broken down into three categories:
- Creational Patterns — creation of objects
- Structural Patterns — provide a relationship between objects
- Behavioural Patterns — define how objects interact
Today, we are going to delve into the Facade Pattern which is classified under the Structural Patterns. Just as its name suggests, it is the face of the architecture. A facade is an object that serves as a front-facing interface for the client to access the system but also masks the complexities of the system and the code structure.
As shown in the diagram below, The Facade class sits between the subsystems and the users of the subsystems, such that all access to the subsystems happens through the Facade class. Several clients can now acquire the information of different subsystems without being exposed to the complexities of the subsystems.
Implementing the Facade Pattern
Context: You are a Bubble Tea lover. A Bubble Tea shop has 2 Branches which sell different drinks in each branch. As a Client, you want to know the drinks sold by the different branches but you can only access the BubbleTeaManager class who knows all the drinks sold by each branch. If you want to know the drinks sold by a particular branch, simply tell the BubbleTeaManager and he will display all the drinks sold by that branch. Now, shall we take a look at the code?
public interface BubbleTea {
public Drinks getDrinks();
}public class OrchardBranch implements BubbleTea { public Drinks getDrinks() { OrchardBranchDrinks drinks = new OrchardBranchDrinks(); return drinks; }}
public class SomersetBranch implements BubbleTea { public Drinks getDrinks() { SomersetBranchDrinks drinks = new SomersetBranchDrinks(); return drinks; }}
From the above code, we have the BubbleTea interface which has a method that returns the Drinks sold. Next, the OrchardBranch class and SomersetBranch class are the 2 different Bubble Tea branches that implement the BubbleTea interface. Following this, let us implement the main character of the day, the BubbleTeaManager class which acts as a Facade as shown below:
public class BubbleTeaManager { public OrchardBranchDrinks getOrchardBranchDrinks() { OrchardBranch ob = new OrchardBranch(); OrchardBranchDrinks drinks = (OrchardBranchDrinks)ob.getDrinks(); return drinks; } public SomersetBranchDrinks getSomersetBranchDrinks() { SomersetBranch sb = new SomersetBranch(); SomersetBranchDrinks drinks = (SomersetBranchDrinks)sb.getDrinks(); return drinks; }
}
Here we have the BubbleTeaManager which acts as a Facade, which knows every single drink sold by the different branches. The complex implementation will be done by the BubbleTeaManager class itself, where the Client can directly access it by querying the drinks sold by the different Bubble Tea branches. The Client can now retrieve the different drinks as shown below:
public class Client { public static void main (String[] args) { BubbleTeaManager btm = new BubbleTeaManager(); OrchardBranchDrinks obd = btm.getOrchardBranchDrinks() SomersetBranchDrinks sbd = btm.getSomersetBranchDrinks(); }}
With the given BubbleTeaManager class, the Client can just access the interface to retrieve all the drinks sold by the different branches without having to know all the complex details of the code. Hence, this is how the Facade class can encapsulate all the functionality and hide it from the rest of the code. It knows where to direct the Client’s request and how to operate all the moving parts.
Here is the class diagram of the implementation of the Facade pattern. As shown above, the Client will not be exposed to the code and structure of the Subsystems(OrchardBranch and SomersetBranch classes, BubbleTea interface) when it requests the BubbleTeaManager facade to perform some action. The Facade class then helps in delegating the Client’s requests to the following subsystems.
Conclusion
The Facade pattern is useful in hiding the internal structure of a component from the clients of that component. You can also make an external communication layer over an existing system that is incompatible with the system using the Facade Pattern. Next, it also loosens the coupling between clients and the subsystems as we are now able to isolate the code from the complexity of the subsystems. Along with the observer pattern, clients can communicate with the component without having a direct dependency on it. Do consider incorporating the Facade pattern in your code as it can handle the underlying interactions with the subsystems transparently from the clients!
Thank you for taking the time to read my very first post! Please feel free to leave some feedbacks. Thank you and have a great day ahead!
References: