Facade Design Pattern in C#

A Facade is a structural design pattern providing a simplified interface to a larger code, such as a library or complex class. In this article, I will write about the Facade Design Pattern in C#.

What is a facade design pattern?

The Facade design pattern encapsulates the complex logic and provides a simplified API to the end user. Often, a seemingly simple operation may contain quite complex code, hidden in the background, and just a simple method is exposed to the public. That method may use a lot of the complex code itself, but the end user doesnโ€™t know about it. The exposed public API acts like a Facade behind which, the complex logic is hidden. The Facade is represented by the following UML diagram:

Facade Design Pattern โ€“ UML Diagram
Facade Design Pattern โ€“ UML Diagram

Example with C#

Imagine you are working on an application for online ticket purchases for different events. Your Facade can expose the BuyTicket method, which in the background is using a lot of other services for printing the ticket, accepting the payment, and sending the ticket via email. But you donโ€™t care about these services, you just need to buy your ticket, so they are hidden behind a Facade.

Letโ€™s look at the following example:

C#
public class TicketFacade
{
    private const decimal RegularTicketPrice = 1000m;

    private const decimal VIPTicketPrice = 2000m;

    public void BuyTicket(PurchaseInfo purchaseInfo)
    {
        // 1. Set the seat as reserved
        this.SetSeatStatus(purchaseInfo.SeatNumber, SeatStatus.Reserverd);

        // 2. Process the payment
        var paymentService = new PaymentService();
        var price = this.GetPrice(purchaseInfo.TicketType);
        bool isPaymentSuccessful = paymentService.ProcessCardPayment(price, purchaseInfo.PaymentInfo);

        if (isPaymentSuccessful)
        {
            // 3. Generate reciept, ticket and invoice
            var printService = new PrintService();
            string reciept = printService.PrintReciept(price);
            string ticket = printService.PrintTicket(price, purchaseInfo.BuyerInfo.Name, purchaseInfo.SeatNumber);

            string invoice = string.Empty;
            if (purchaseInfo.GenerateInvoice)
            {
                invoice = printService.PrintInvoice(price, purchaseInfo.BuyerInfo.Name);
            }

            // 4. Send the generated items via email to the buyer
            var emailSenderService = new EmailSenderService();
            emailSenderService.SendEmail(purchaseInfo.BuyerInfo.Email, reciept, ticket, invoice);
        }
        else
        {
            // If payment fails - unreserve the seat
            this.SetSeatStatus(purchaseInfo.SeatNumber, SeatStatus.NotReserved);
        }
    }

    private decimal GetPrice(TicketType ticketType)
    {
        var price = RegularTicketPrice;
        if (ticketType == TicketType.VIP)
            price = VIPTicketPrice;

        return price;
    }

    private void SetSeatStatus(int seatNumber, SeatStatus seatStatus)
    {
        // a Database call to mark the seleced seat as reserved/unrserved
    }
}

The BuyTicket method accepts purchase information, needed for the online purchase. To buy the ticket you perform the following logic:

  • Reserve the seat, so that no one else can select it
  • Call the payment service and process a request to the bank:
C#
internal class PaymentService
{
    internal bool ProcessCardPayment(decimal price, PaymentInfo paymentInfo)
    {
        var result = false;

        using (var client = new HttpClient())
        {
            // process payment request to the bank
        }

        return result;
    }
}

public class PaymentInfo
{
    public string CardNumber { get; set; }

    public DateTime CardExpirationDate { get; set; }

    public string CardSecurityCode { get; set; }
}
  • If the payment is successful โ€“ call the print service and generate a receipt and a ticket:
C#
internal class PrintService
{
    internal string PrintReciept(decimal price)
    {
        var result = string.Empty;

        // generate the reciept

        return result;
    }

    internal string PrintTicket(decimal price, string buyerName, int seatNumber)
    {
        var result = string.Empty;

        // generate the ticket

        return result;
    }

    internal string PrintInvoice(decimal price, string buyerName)
    {
        var result = string.Empty;

        // generate the invoice

        return result;
    }
}
  • If the customer has chosen to be invoiced โ€“ generate an invoice
  • And finally โ€“ send the generated outcome to the email
  • If the payment wasnโ€™t successful mark the seat as not reserved

As you can see the BuyTicket method does a lot of stuff, to finalize the purchase, but this logic is hidden behind a facade. You just pass the purchase info and get your ticket via email. The user of the code doesnโ€™t have to worry about, printing, payment, or anything else accompanying the purchase process.

Downloads