Java Facade Design Pattern Example
1. Introduction
In an enterprise application, it is extremely important to manage the code base so that the redundancy is reduced. Moreover, in order to make code manageable, we also need to take care that the classes are structured and connected so that the generic code is not repeated in multiple classes. In Java, we use the features like implementing an interface or extending a class for a similar purpose.
You can also check a tutorial in the following video:
To make the code management and design better, Java provides with three major types of design patterns – each with a dedicated purpose. These patterns are:
- Creational Pattern: This pattern category offers a bunch of child patterns that emphasise on the logic of instantiation of objects while concealing the actual implementation of the objects. Thus, this pattern controls the objects that should be created for every module.
- Structural Pattern: This pattern category offers a bunch of child patterns to help the developers organise the class structure so that the desired classes and features are exposed in a desired manner. Additionally, they offers solutions to problems like interfacing different types of objects, entities or applications.
- Behavioural Pattern: This pattern category is mainly associated with the way objects communicate with each other
In this article, we will be discussing one of the structural pattern – Facade Design Pattern. Facade, talking about the dictionary meaning, it means the front area outside a building or a site. It is the space that support the handling of that building by providing easily accessible parking space, plantation space as well as utility space. Similarly, the Facade Design Pattern, as the name indicates, provides a front facing class to hide the backend logics used to do certain specific tasks. These tasks are majorly complicated tasks for which the developer does not want others to access the core functionalities. Going further in the article, we will try to understand the design pattern logically using sample class diagrams and later proceed towards coding few classes to implement a Facade class.
2. Understanding the Facade design pattern
In a large application consisting of numerous features, there is often a scenario where certain complex code implementations need to be kept concealed or covered to avoid tempering with the core coding. Few such scenarios could be – An encryption & decryption process for the data, core object processing to extract data, database connection and data processing, communication APIs and others. First of all, lets us consider the below image that depicts the Facade design pattern.
As it can be seen in the above image, the client block is the class that needs to call complicated functional implementations from class 1 or class 2. However, those implementations are critical and hence the author of the class is unwilling to expose the implementation. Due to this, we develop a Facade class. The facade class would contain a simple method call which does all the necessary function calls for the complicated classes. These function calls are made using an if else ladder or based on flag passed as argument to the simple function in the Facade class.
Now let us consider the scenario of encryption and decryption of data. The below image provides a bunch of classes used for encryption. Those are the complicated classes discussed above.
In the above diagram, there are three different classes that employ different encryption methods on the data that is passed. The class have the code customised as per the need of the organisation and contains the relevant private keys used for encryption where needed. These classes are expected to be concealed from the developer using them. However, developer needs to utilise the encryption methods to make sure that the data is encrypted before it is saved.
In such a scenario, we provide a facade class. A facade class is basically the front-face or the exposed class for the use of these functionalities. The facade class needs to take care of the following:
- Take in inputs from the class using it
- Conditionally call the relevant functions from the encryptor classes
- Provide a common method that encrypts according to the supplied parameters
- Return the encrypted data to the calling class
These functionalities are implemented at the facade class without exposing the code related to the functions. The facade class will utilise the objects of the relevant class within it and make the necessary function calls. In this manner, the author of actual classes just need to convey the functions written to serve the purpose.
Now, let us jump into coding an implementation using the Facade design pattern. We will be using the same example as discussed above. We will follow the below steps:
- Create the Encryptor classes
- Create the Facade class to expose its functionality
- Create the Client class to consume the Facade class
3. Coding Facade class
The first step towards coding in a Facade design pattern is to code the complicated classes. Create the three encryption classes as shown below. These classes will each perform three actions:
- Take text as input in a function
- Use the respective encryption algorithm
- Convert the hashed text to hex and return it.
MD5Encryptor.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | package com.javacodegeeks.abk; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Encryptor { public String encrypt(String text) { String hash = "" ; try { MessageDigest msgDigest = MessageDigest.getInstance( "MD5" ); msgDigest.update(text.getBytes()); byte textBytes[] = msgDigest.digest(); StringBuffer buffer = new StringBuffer(); for ( int i = 0 ; i < textBytes.length; i++) { buffer.append(Integer.toString((textBytes[i] & 0xff ) + 0x100 , 16 ).substring( 1 )); } hash = buffer.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return hash; } } |
SHA.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.javacodegeeks.abk; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SHA { public String encrypt(String text) { String hash = "" ; try { MessageDigest digest = MessageDigest.getInstance( "SHA" ); byte [] textBytes = digest.digest(text.getBytes(StandardCharsets.UTF_8)); StringBuffer buffer = new StringBuffer(); for ( int i = 0 ; i < textBytes.length; i++) { buffer.append(Integer.toString((textBytes[i] & 0xff ) + 0x100 , 16 ).substring( 1 )); } hash = buffer.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return hash; } } |
SHA256.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.javacodegeeks.abk; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SHA256 { public String encrypt(String text) { String hash = "" ; try { MessageDigest digest = MessageDigest.getInstance( "SHA-256" ); byte [] textBytes = digest.digest(text.getBytes(StandardCharsets.UTF_8)); StringBuffer buffer = new StringBuffer(); for ( int i = 0 ; i < textBytes.length; i++) { buffer.append(Integer.toString((textBytes[i] & 0xff ) + 0x100 , 16 ).substring( 1 )); } hash = buffer.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return hash; } } |
The above classes utilise the java.security
libraries to generate hashed value of the provided text. Note here that we are fetching a specific type of message digest in each class. The author expects that the class always does only the designated tasks. In order to do so, the author would prefer to hide the class by providing a Facade class taking care of the function calls. This will eliminate the risk of any tempering with the code of these core classes. These are very basic level examples of how complicated the implementations could be. They could contain complete encrypted insertion code for different databases too!
Now, we understand what a complicated class is. It is time to create a facade classes that exposes these complicated class functionalities using variables. The below code shows a Facade class created to expose these functionalities. The facade classes will do the below items:
- Expose a method that takes in two arguments – A type specifying which encryption method will be used and another to specify the text that needs to be hashed
- Create a conditional ladder to create respective object as per the argument
- Hash the input and return it
EncryptorFacade.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.javacodegeeks.facade; import com.javacodegeeks.abk.MD5Encryptor; import com.javacodegeeks.abk.SHA; import com.javacodegeeks.abk.SHA256; public class EncryptorFacade { public String encrypt(String type, String text) { String hash = "" ; if (type == "MD5" ) { MD5Encryptor e = new MD5Encryptor(); hash = e.encrypt(text); } else if (type == "SHA" ) { SHA e = new SHA(); hash = e.encrypt(text); } else if (type == "SHA256" ) { SHA256 e = new SHA256(); hash = e.encrypt(text); } return hash; } } |
The Facade class above exposes a single public method with two arguments. One of these arguments is the type of hashing that is required and the second argument is the text that needs to be encrypted. Notice here that based on the type of hashing that is required, the Facade classes creates objects of different encryptor classes(complicated classes) and hashes the text accordingly. In this manner, just using a single method, the Facade class took care of the different types of encryption that was possible. This method can now be used by the client directly by creating the object of the facade class. This is demonstrated in the code below.
Client.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | package com.javacodegeeks.client; import com.javacodegeeks.facade.EncryptorFacade; public class Client { public static void main(String[] args) { String myText = "Encrypt this text" ; EncryptorFacade e= new EncryptorFacade(); System.out.println( "MD5 encryption" ); System.out.println(e.encrypt( "MD5" , myText)); System.out.println( "SHA encryption" ); System.out.println(e.encrypt( "SHA" , myText)); System.out.println( "SHA256 encryption" ); System.out.println(e.encrypt( "SHA256" , myText)); } } |
The above class is a client class that will actually consume the method provided by the Facade class. As it can be seen, all that is required to be done is create an object of the Facade class EncryptorFacade
and call the respective method encrypt()
. The output executing the above code will be as shown below.
1 2 3 4 5 6 | MD5 encryption 8608b4eae12d595dce48b6857132d5d0 SHA encryption 68e7b34151cfdd2cd26ffbd0c65aabd8efcf4160 SHA256 encryption 3b41d4bc4fcec64fb0924e9080495520938b17443b11ef41750784872c0d4e8c |
4. Benefits of using Facade pattern
The Facade design pattern is primarily focused on providing a systematic solution to conceal implementation of complicated classes. However, in addition to the improved project structure, there are several other benefits of the Facade Design Pattern. These benefits are explained below
4.1 Reduced memory usage
Consider that there is no Facade class and the complicated class methods are exposed directly. There is no issue in using these methods directly. The code will be slightly modified and client would look like the one shown below.
Client2.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | package com.javacodegeeks.client; import com.javacodegeeks.abk.MD5Encryptor; import com.javacodegeeks.abk.SHA; import com.javacodegeeks.abk.SHA256; public class Client2 { public static void main(String[] args) { String myText = "Encrypt this text" ; MD5Encryptor e= new MD5Encryptor(); System.out.println( "MD5 encryption" ); System.out.println(e.encrypt(myText)); SHA s = new SHA(); System.out.println( "SHA encryption" ); System.out.println(e.encrypt( myText)); SHA256 s256 = new SHA256(); System.out.println( "SHA256 encryption" ); System.out.println(e.encrypt(myText)); } } |
Now, consider almost 10 other such classes in the picture. Each class creates three different objects and makes the calls. The memory consumption will be extremely high. While the Facade class above could be modified and optimised to create a single object per method as a global object and reduce the memory utilisation.
4.2 Reduced efforts in code changes
In the above case, imagine a change where in some new method from the complicated classes needs to be called. For instance, use encrypt2
instead of encrypt
method. Making this change for a bunch of classes could be a lot of effort being wasted. A Facade class comes to rescue here. The Facade class keeps its method signature as it is while implementing the code for the new methods of the complicated classes. This allows the developer of the complicated classes a level of independence in their code.
5. Use of Facade Design Pattern
In the above sections, we discussed the major benefits of Facade pattern and understood the Facade design pattern conceptually. The Facade design pattern is used in the below scenarios:
- It is used when the number of interfaces or complex classes are on the rise and it is necessary to provide a common ground to the group of these complicated classes
- Facade design pattern is useful to simplify the implementation for the application developers by providing a simpler implementation of the complicated classes in the backend
- Facade design pattern is used to introduce a helper class where the sub class may be too complicated for the user to understand
- It is used only when there are a group of classes used for a similar purpose. The Facade class conceptually takes in arguments to conditionally call similar functionalities implemented by different classes.
6. Possible drawbacks
Normally, there are no disadvantages of any design pattern in Java. However, care needs to be taken that the design pattern is used sensibility and not exhaustively. Exhaustive use of the Facade pattern might result in redundant codes which might get complex to manage eventually. Additionally, Facade design pattern does not really conceal the subclasses unless they are packaged separately. Thus, there is certainly potential risk of code tempering if the code is not packaged accordingly.
7. Java Facade Design Pattern – Conclusion
Java design patterns are key to better code management and a better code maintainability. The structural design patterns focus on this aspect in a structural way by providing different ways to simplify the code and yet keep it less redundant. The facade design pattern plays a similar role by reducing the complexity hidden in the sub classes and exposing the functionalities using a simpler function implementation. Thus, Facade design pattern if used in a proper manner, can lead to excellent simplification of complex code and reduce the development time consumed.
8. Download the Source Code
That was Java Facade Design Pattern Example.
You can download the full source code of this example here: Facade Design Eclipse.zip
Well explained!
Thank you.