Facade Pattern

Hello everyone, and welcome to .NET Core Central. In this blog post, I am going to walk through the facade pattern.

The facade design pattern is also one of the Gang Of Four design patterns. The facade design pattern is a structural design pattern.

The main intent of this pattern is to provide a unified interface instead of exposing a set of interfaces from a subsystem. When we get into the details it will be a little bit more clear what this sentence means.

But is important to understand that, in the above statement, the interface literally does not mean just the C# interface concept. An interface in this case is any set of interfaces to a particular subsystem. Which can be a service, it can be an interface, and so on and so forth.

The use case for Facade Pattern

The facade pattern defines a high-level interface that makes the underlying services easier to use. Now let us take an example and it will be clear what I mean by this statement.

Note:

The facade pattern is probably one of the easiest and simplest design patterns out there. And in a lot of cases, we use facade patterns without even knowing about it.

So let us take an example, let us say we have an e-commerce system. And the e-commerce system deals with buying some items.

And for buying items what all do we need?

  • Firstly, we will need an inventory system that is going to be responsible for showing the inventory.
  • Secondly, we will have a payment system that will be responsible for the payment processing.
  • And then finally we might have a notification system that is responsible for sending notifications.

Interfaces and class details

I am going to use .NET 6.0 framework and C# language for this blog post.

So if we have to do that in the code, what we can do is create three new interfaces.

Inventory Service

The first interface will be IInventoryService. For simplicity let’s consider it is a full-fledged inventory interface, which will provide all the functionality of an inventory. But in a real-life scenario, you’ll be probably breaking it out into inventory provider versus inventory search versus inventory creator, and so on and so forth.

For the time being, let us say we just have an inventory service. And the inventory service is going to have just one method. The method name will be GetAsync and it will have a return type of string array. And this method will be responsible for returning all inventory.

public interface IInventoryService
{
    Task<string[]> GetAsync();
}

Next, as a part of the inventory service module, let us create the InventoryService class. The InventoryService class will implement the IInventoryService interface. And for the implementation of the GetAsync method, we will just return a hardcoded array of two string values.

internal class InventoryService : IInventoryService
{
    public Task<string[]> GetAsync()
    {
        return Task.FromResult(new string[] {"Book", "Pen"});
    }
}

Note:

The implementation here for this blog post is very simple for the purpose of demonstration.

Payment Service

Next, we will have another service called the payment service. Hence for that, we will create another interface IPaymentService. And this interface will have one method PayAsync, which will not return anything (just a Task). And the PayAsync method will take two parameters, double amount and string item.

public interface IPaymentService
{
    Task PayAsync(double amount, string item);
}

Next, as a part of the payment service module, let us create the PaymentService class. The PaymentService class will implement the IPaymentService interface. And for the implementation of the PayAsync method, we will just write a message to the console using the Console.WriteLine statement.

internal class PaymentService : IPaymentService
{
    public Task PayAsync(double amount, string item)
    {
        Console.WriteLine($"Paying amount: {amount} for item: {item}");
        return Task.CompletedTask;
    }
}

Notification Service

Finally, we will have another interface which is INotificationService. This interface is responsible for sending notifications. And this interface will have a single method SendAsync, which will not return anything (just a Task). The SendAsync method will take a single parameter string message.

public interface INotificationService
{
    Task SendAsync(string message);
}

Next, as a part of the notification service module, let us create the NotificationService class. The NotificationService class will implement the INotificationService interface. And for the implementation of the SendAsync method, we will just write a message to the console using the Console.WriteLine statement.

internal class NotificationService : INotificationService
{
    public Task SendAsync(string message)
    {
        Console.WriteLine($"Sending notification message: {message}");
        return Task.CompletedTask;
    }
}

Note:

All of these methods from the interfaces are async methods because in a real-life scenario, they will be working with external services like sending emails, saving payments, and getting inventory. And these activities will be through calling an external service or data store, which will be done asynchronously.

But for the purpose of the blog, I am just going to do Console.WriteLine.

Controller Classes

After the business classes are ready, we will go ahead and create three different controllers representing the three business classes.

Payment controller

The first controller we will create is for payment purposes. So we will name this as PaymentController. For creating the controller, we will use the API Controller with read/write actions template.

Inside the controller, we will create a constructor. And in the constructor will inject the IPaymentService interface as a parameter.

Next, I will provide an implementation for the Post method of the controller. And I will delete all the methods that come with the template.

I will update the post method to take two parameters from the request body. The first one is the string item and the second one is the double payment. And inside the Post method, I will just call the PayAsync method of the IPaymentService interface passing the amount and item.

using Microsoft.AspNetCore.Mvc;

namespace FacadePattern.Demo.Controllers;

[Route("api/[controller]")]
[ApiController]
public class PaymentController : ControllerBase
{
    private readonly IPaymentService paymentService;

    public PaymentController(IPaymentService paymentService)
    {
        this.paymentService = paymentService;
    }

    // POST api/<PaymentController>
    [HttpPost]
    public async Task Post([FromBody] string item, [FromBody] double amount)
    {
        await paymentService.PayAsync(amount, item);
    }
}

Notification Controller

Similar to the PaymentController, we will add another controller. And this controller also is going to be a controller for sending notifications. So we will name this controller as NotificationController.

And for the NotificationController as well, we will just have the Post method. And next, we will create a constructor for the controller. And we will inject the INotificationService interface as a parameter to the constructor.

And finally, we will update the parameter name of the Post method from value to message. Inside of the Post method, we will call the SendAsync of the INotificationService passing the incoming message from the Post method.

using Microsoft.AspNetCore.Mvc;

namespace FacadePattern.Demo.Controllers;

[Route("api/[controller]")]
[ApiController]
public class NotificationController : ControllerBase
{
    private readonly INotificationService notificationService;

    public NotificationController(INotificationService notificationService)
    {
        this.notificationService = notificationService;
    }

    // POST api/<NotificationController>
    [HttpPost]
    public async Task Post([FromBody] string message)
    {
        await notificationService.SendAsync(message);
    }
}

InventoryController

The third and last controller is going to be the InventoryController. And in the InventoryController we are just going to have the Get method, and we will delete the rest of the methods.

We will create a constructor for the InventoryController. And we will inject the IInventoryService interface as a parameter to the constructor.

Inside the Get method, we will call the GetAsync method of the IInventoryService and return the string array.

using Microsoft.AspNetCore.Mvc;

namespace FacadePattern.Demo.Controllers;

[Route("api/[controller]")]
[ApiController]
public class InventoryController : ControllerBase
{
    // GET: api/<InventoryController>
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

The case for Facade Pattern

So at this point in time, we have three controllers ready. And with the help of these three controllers, we can get all inventory, make payments, and send notifications.

Now consider that these services are accessed from your web application or a mobile client. As a part of the workflow, the client is first going to make a call to get all inventories using the InventryController.

And then it will make a call to the PaymentController to send payment. Finally, it will call the NotificationController to send notifications.

The inventory call might be done twice, the first time when all the inventory is loaded. And a second time when someone buys something it will make the inventory call again to verify if the inventory is still there and then make a purchase through the PaymentController.

This scenario causes two issues, the first issue is now the client has to make multiple calls. Secondly, there are too many granular-level services exposed to the client.

So how do we solve this? This is exactly the situation where the facade pattern should be used.

Purchase facade

At this point, we can create a new controller and we can call it as PurchaseFacadeController. And the PurchaseFacadeController is now going to act as a facade for all the other controllers. Hence, instead of calling individual controllers, the client can call the PurchaseFacadeController to get all the functionality of a purchase.

In the PurchaseFacadeController first, I will create a constructor. And in the constructor, I will inject IInventoryService, IPaymentService, and the INotificationService as parameters.

Next, I will only keep the Post method inside the controller. And I will update the Post method to take the string item and double amount from the FormBody.

Since the Post method is going to be the facade for the rest of the services, hence,

  • Firstly, we are going to call the GetAsync method from the IInventoryService and get all inventories.
  • Secondly, it will check if the item sent in the request is available in the inventory. And if it does, it is going to call the PayAsync method of the IPaymentService to pay for the item.
  • And finally, call the SendAsync method of the INotificationService to send a notification.
using Microsoft.AspNetCore.Mvc;

namespace FacadePattern.Demo.Controllers;

[Route("api/[controller]")]
[ApiController]
public class PurchaseFacadeController : ControllerBase
{
    private readonly IInventoryService inventoryService;
    private readonly IPaymentService paymentService;
    private readonly INotificationService notificationService;

    public PurchaseFacadeController(IInventoryService inventoryService,
        IPaymentService paymentService,
        INotificationService notificationService)
    {
        this.inventoryService = inventoryService;
        this.paymentService = paymentService;
        this.notificationService = notificationService;
    }

    // POST api/<PurchaseFacadeController>
    [HttpPost]
    public async Task<IActionResult> Post([FromBody] string item, [FromBody] double amount)
    {
        var inventories = await inventoryService.GetAsync();
        if (inventories.Any(i => i == item)) return BadRequest();

        await paymentService.PayAsync(amount, item);

        await notificationService.SendAsync($"Item: {item} purchased with amount: {amount}");

        return Ok();
    }
}

What we did here is that we created a facade, and now instead of calling three different controllers or three different Web APIs, the client can just call this facade and do the purchase as a part of a single call. And this is where the facade pattern comes in very handy.

Microservice scenario for Facade Pattern

The next question you might have is when working in a microservices environment, the inventory, notification, and payment are going to be different microservices. In that case, how will the facade pattern work?

There are two ways we can achieve this in the case of microservices:

  • The first way to achieve this is the PurchaseFacadeController itself can be its own microservice. And it is the one that is going to expose this Post method and internally it will be making HTTP Get and Post calls to all the other three microservices and acts as a facade.
  • And the second way of doing this is to use an API gateway. And in the API gateway implementation, you can call these microservices from the API gateway through orchestration. And in this case, the API gateway will be the facade for the three microservices.

Conclusion

As I mentioned at the beginning of this blog post, you might be using this pattern very frequently. This pattern comes very naturally when you are building services using the SOLID design principles.

And if you are using microservices, there are a lot of scenarios where you will end up having a facade service through an API gateway to orchestrate your microservices. Or having another microservice to act as a facade.

A Youtube video for this implementation is available here.