Facade Design Pattern - Definition

The Facade Design Pattern provides a unified interface to a set of interfaces in a subsystem. It defines a higher level interface that makes the subsystem easier to use.

Use case - Order processing application

Let us consider the use case of making an online purchase. After we place an order and it confirms the order, it debits the money. It then ships the product.

Steps to process an order

It consists of the following steps:

Note: This is to give an idea to illustrate the facade pattern. The actual steps to implement an ordering system will defer.

Validation and pre-checks

  1. Validating if the customer account is not blocked
  2. Checking if the customer is eligible for making this purchase.
  3. Validating if the card is valid
  4. Checking the inventory
  5. Applying discounts (if any)

First, we validate the customer account and is not blocked or blacklisted. Second, we ensure that the customer is eligible to make this purchase. It is to catch any scenario where the mischievous customer has somehow managed to add a product to the cart which is not available to him/her (say based on region). Third, we check the validity of the credit/debit card used for the purchase. Fourth, the product’s inventory is checked for availability (since the product would have been sold out after the customer has added it to the cart and before making the purchase). Fifth, we apply any available discounts to the customer.

We have completed the pre-checks to place the order and now the customer is all good to make this purchase. Let us continue.

Making the purchase

  1. Debit the money from the card
  2. Add the purchase details to the customer account
  3. Prepare for shipping by sending the order details to the shipping section/department
  4. If any cash back is available, apply it to the customer

I guess the above steps are self-explanatory. In summary, the purchase step debits the card and prepares for shipping the items. If the customer is eligible for any cash back, we credit it to the customer’s account (customer’s valet).

That makes a total of 9 steps. Wouldn’t you agree it is tedious to do all these if you were asked to implement it especially if the exact sequence of steps were needed to be done from multiple places in the code?

The subsystems

Let us look at the class diagram representation of the above system.

FacadeSubsystemsClassDiagram

Each of the Service classes here are called a subsystem. They are isolated unit that performs some behaviour. To implement our use case of placing an order, we had to interact with all of these subsystems. It becomes difficult if all the clients have to interact with so many subsystems to implement a method.

We can use a facade to simplify this.

A Facade

To use the Facade Design Pattern, we create a class (the facade) that simplifies and unifies a set of more complex classes that belong to some subsystem.

The key words here are simplifies and unifies a set of classes. A facade provides a simplified interface to the clients. The implementation of that interface takes care of interacting with the complex subsystem to achieve the end goal.

Let us look at the facade implementation.

public class OrderProcessingFacade {
    private CustomerService customerService;
    private DiscountService discountService;
    private InventoryService inventoryService;
    private PaymentService paymentService;
    private ShippingService shippingService;

    public OrderProcessingFacade(CustomerService customerService, DiscountService discountService,
                                 InventoryService inventoryService, PaymentService paymentService,
                                 ShippingService shippingService) {
        this.customerService = customerService;
        this.discountService = discountService;
        this.inventoryService = inventoryService;
        this.paymentService = paymentService;
        this.shippingService = shippingService;
    }

    public void processOrder(Order order, CustomerAccount account, Card card) {
        customerService.validateAccount(account);
        customerService.isEligible(order);

        paymentService.validateCard(card);

        for (Product product : order.getProducts()) {
            inventoryService.checkAvailability(product);
        }
        Order discountedOrder = discountService.applyDiscount(order);

        paymentService.debitCard(discountedOrder, card);
        customerService.applyOrder(discountedOrder);
        shippingService.shipForOrder(discountedOrder);

        boolean cashbackAvailable = order.isCashbackAvailable();
        if (cashbackAvailable) {
            customerService.applyCashBack(order);
        }
  }
}

The OrderProcessingFacade is our facade class. The processOrder is the simplified and unified interface we provide to the clients. Now, all a client need to do is to call the processOrder method. Behind the scenes, the facade does all the 9 steps discussed earlier. It validates the account, the card, applies discount, debits the card, places order for shipping, applies any cash back to the customer’s account.

The Facade is responsible for talking to numerous other subsystem classes. This reduces and abstracts the complexity for the client.

Facade pattern - Representation

The facade is the single dependency for the client. It takes care of co-ordinating with the subsystems.

FacadeDesignPatternSubsystems

Participants

Facade (OrderProcessingFacade)

  • It knows which subsystem classes are responsible for a request.
  • It takes care of delegating a client request to various subsystem objects.

Subsystem classes (CustomerService, InventoryService etc.)

  • They implement the subsystem functionality.
  • Does work when called by the facade.
  • They are decoupled from the facade and the client i.e., they are not aware of the facade and the client.

Advantages of the Facade Design Pattern

It enables us to provide a simple interface to a complex system.

The facade acts as the entry point into the complex subsytem. The subsystem can evolve in the future and this doesn’t affect any client as they are confined by and within the facade. Hence, the clients and the facade are decoupled.

Since the subsystems and the clients are decoupled, we can easily switch a subsystem implementation with another(Strategy Design Pattern).

Example: When a new InventoryService v2 is available, we only have to change the facade to call the new service. The client is unaffected and does not even know about this swap.

Things to note

A key point in facade is that the facade does not encapsulate the subsystems. It just provides a simplified interface for operations that depend on multiple subsystems. The subsystem classes are still available for use by any client. For example, if any part of the application wants to check the inventory, it can directly use the InventoryService for this.

A facade can do other things as well (apart from just calling the subsystem methods).

A facade of facade

Why not? We can mix and match the component subsystems to create a facade to use another facade. In our example, we can move the validation and pre-checks alone into a facade and use it from the order processing facade. This has two advantages

  1. It simplifies the work of one facade
  2. Enables reusability - We can reuse the facade logic that does the pre-check validation steps alone if needed.

Design principles used

  1. Program to an interface, not implementations
  2. Favour composition over inheritance

Conclusion

We looked at how a complex steps or sequence of actions implementing an operation can be wrapped as a facade to provide a simpler and unified interface to the clients. This decouples the client from the subsystems that does part of the work. But the facade does not encapsulate the subsystems and are available for use if needed.

Liked my post? Leave a comment to let me know what you thought.

Check out the other design patterns too from here.

References