🌑 Outline
A pattern to provide a simple interface to a complex framework or library. It hides the complexity and interaction between different objects in the framework.
Facade - Face of a building.
🌥️ Why Facade
Suppose you are working on an e-commerce application. You have to support multiple payment options like UPI, Credit card, Debit Card, Wallet etc. You have chosen a third-party payment gateway which provides support for all types of payments. The payment gateway has an initiation setup (API key, session) and multiple objects for payment methods.
If you write all the logic in your application class then your class object is required to manage all the payment objects and track the life cycle of those objects. In this way, your code will be tightly dependent upon third-party payment SDK.
![](/assets/img/cleancode/designpattern/facade/facadeProblem.png)
To make things simple we can use here Facade Design Pattern.
🌛 = 🌜 Metaphor
![](/assets/img/cleancode/designpattern/facade/facadeMetaphor.jpg)
A desktop computer on your table is a good example of a facade pattern. You just need to press the power button and everything is behind-the-scenes. The power supply sends electricity to all components and then initializes the BIOS, Load instructions from ROM, etc.
All these complex tasks happen secretly and the person sitting in front just has a single interface a Power button :).
🌓 Talk is cheap. Show me the code
In the Facade pattern, a class is created to provide a simple interface for a complex system.
![](/assets/img/cleancode/designpattern/facade/facadeSolution.png)
Code Snippet
//Enum to identify payment type.
enum SupportedPaymentFacade {
case wallet
case upi
case card
}
//Payment Information.
struct PaymentInfo {
let skuID: String
let amount: Int
let method: SupportedPaymentFacade
}
// sample class which represent the complex third party framework
class PaymentSDKUmbrella {
let walletSDK: PSWallet
let upiSDK: PSUPI
let cardSDK: PSCard
}
// Facade class application interact with this object. Application will not aware about PaymentSDKUmbrella.
class PaymentFacade {
var paymentSDKUmbrella: PaymentSDKUmbrella?
func doPayment(_ paymentInfo: PaymentInfo) {
switch paymentInfo.method {
case .card:
cardSDK.doPayment(paymentInfo.amount)
case .upi:
upi.doPayment(paymentInfo.amount)
case .wallet:
if walletSDK.hasSufficientAmount(paymentInfo.amount) {
walletSDK.doPayment(paymentInfo.amount)
} else {
print("Insufficient balance")
walletSDK.addPayment(paymentInfo.amount)
}
}
}
}
//Application uses of facade class
class AppPaymentController {
let facade = PaymentFacade()
func startPayment(for product: Product, paymentMethod: SupportedPaymentFacade) {
let paymentInfo = PaymentInfo(skuID: product.skuID, amount: product.amount, method: paymentMethod)
facade.doPayment(paymentInfo)
}
}
Applicability
Complex Library
Integrating a library which has multiple subsystems can be done through the facade pattern. Also, if the library is used at multiple places then to avoid the redundant code of init and setup the library facade can be used. In the above example, payment SDK has multiple sub-systems like wallet, net banking and Card payment. So you can create a facade class in a way that your application has minimal knowledge of all the dependencies of the payment SDK.
Small Interfaces
Use a facade pattern when you want to use limited functionality from a complex library. In the case of payment SDK, if you want to use only wallet and card payment in your application then you can create a facade class to support only those features.
Facts
Adapter vs Facade Pattern
Mediator vs Facade Pattern
Advantages
You must have been feeling now that the use of the facade pattern is just that the responsibility of interaction to complex system is shifted to facade class.
Decoupling
It is always considered good practice that your application code should not directly depend upon the third-party library interface. Facade patterns provide a simple interface to a complex framework, in a way you also achieve decoupling here. Like in the above case your application code depends upon the Facade class, so if in the future library code changes then only the Facade class will be impacted.
Reusability
In some use cases, the same library needs to be used from multiple places. Like in the above case payment can be done from multiple screens, so instead of the user accessing the library code at each screen the facade class can be used which also reduces the library setup/init burden at every place.
Readability
Most of the time library/framework code is legacy code. Coding convention changes from time to time and the library interface might not fit your current coding convention, So the facade can be used to make code consistent in your application.
Comments powered by Disqus.