Home Simplified Facade Pattern (Structure Pattern)
Post
Cancel

Simplified Facade Pattern (Structure Pattern)

🌑 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.

To make things simple we can use here Facade Design Pattern.

🌛 = 🌜 Metaphor

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.



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

The facade provides a new interface to interact with a complex framework. However, the adapter fits the new object in the existing interface.
An adapter or wrapper pattern is usually for a single object. However, Facade also interacts with multiple objects.


Mediator vs Facade Pattern

The mediator class is used for providing the interaction between sub-components. However, the facade class is used for providing access (simple interface) to sub-components of a large component.
In the case of the mediator, sub-components are aware of the mediator class but the facade class is only visible to the application using sub-components.


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.

This post is licensed under CC BY 4.0 by the author.

Flutter on Apple Silicon Mac: Cocoa-pods Issue

Simplify Decorator Pattern (Structure Pattern)

Comments powered by Disqus.