Facade design pattern real world example In C# - Shopping Cart

Last Updated: 2023-12-24 14:16:34

Previously we have discussed the Facade design pattern with a real-life example. We have explained this pattern with a cooking system example. Now in this post, we will discuss the facade design pattern with another real-life example which is the Shopping Cart system.

 

You may already know that the main purpose of the facade design pattern is to make a complex system easy to use on the client side. Hence in this post, we will create a complex shopping cart system and then we will make it easy using the facade design pattern.

 

The benefit of facade design pattern

The Facade design pattern is like a "shortcut" for using a complicated system. It provides a simple and easy-to-use interface to interact with the complex parts of the system. Instead of dealing with all the complicated details directly, you just use the Facade to do what you need. It makes your code easier to read, maintain, and reuse. It's like having a front desk at a hotel - you talk to the front desk (the Facade) to handle all your requests, and you don't need to worry about what's happening behind the scenes in the hotel (the complex system).

 

 

 

  1. Simplified interface: The facade pattern hides the complexities of the underlying subsystem by providing a simplified interface to the client. This reduces the number of interactions the client needs to make with individual components of the subsystem, making it easier to use and understand.
  2. Encapsulation: The Facade acts as a single entry point to the subsystem and encapsulates its implementation details. It shields the client from the internal workings of the subsystem, promoting loose coupling between the client and the subsystem classes. This allows the subsystem to evolve independently without affecting the client code.
  3. Improved maintainability: Since the complexity of the subsystem is contained within the Facade, any changes or updates to the underlying subsystem can be managed in one place. This simplifies maintenance and reduces the risk of introducing bugs or errors when making modifications.
  4. Reusability: The Facade can be used as an interface for different clients, promoting code reuse. Multiple clients can interact with the same subsystem through the same Facade, avoiding the need to duplicate code or create redundant interfaces.
  5. Decoupling: The Facade pattern decouples the client code from the implementation details of the subsystem. This separation allows for more flexibility in changing or extending the subsystem without impacting the clients using the Facade.
  6. Improved readability: By providing a high-level, easy-to-understand interface, the Facade pattern improves the overall readability of the client code. It makes the codebase more intuitive and maintains a clear separation of concerns.
  7. Performance optimization: In some cases, the Facade pattern can optimize performance by providing specialized methods that combine or rearrange calls to the subsystem to minimize overhead or redundant operations.

 

Facade design pattern real-life example in shopping cart

Imagine you are a customer using an online shopping website. This website has a sophisticated shopping cart system that handles various tasks, such as checking product availability, managing inventory, processing payments, and confirming orders. However, as a customer, you are only interested in two simple actions: creating a cart to add products and placing an order for those products.

 

Facade Design Pattern Real World Example - Shopping Cart

 

 

The shopping website's developers understand the complexity of the shopping cart system and want to simplify it for you. So, they implement the Facade design pattern.

In this scenario:

  1. The complex shopping cart system with multiple classes and interactions represents the "complex subsystem."
    The simple and unified interface, which you as a customer can use, is the "Facade."
    The Facade exposes only two methods to you:
  2. CreateCart(ProductID, Qty): This method allows you to create a cart and add products to it. Behind the scenes, it handles all the intricate details like checking product availability, managing inventory, and locking products in stock.
  3. PlaceOrder(OrderID, UserID): Once you have added the desired products to your cart, you can use this method to place an order. The Facade takes care of tasks like adding tax, assigning address details, verifying your balance, processing payment, and confirming the order.

As a customer, you don't need to understand or deal with the internal complexities of the shopping cart system. You interact with the Facade, which acts as a simplified front-end for you, hiding all the intricate operations happening behind the scenes.

 

In summary, the Facade pattern simplifies the shopping experience for you as a customer. You only need to know how to call the CreateCart and PlaceOrder methods, while the Facade takes care of all the complex tasks related to the shopping cart system.

 

Here's a simplified code example in C#:

 


// complex shopping cart system
public interface ICart
{
    void GetProductDetails(int ProductID);
    void CheckProductAvailability(int ProductID);
    void LockProductInStock(int ProductID, int Qty);
    void AddProductToCart(int ProductID, int Qty);
}

public interface IOrder
{
    void AddTax(int OrderID);
    void AssignAddressDetails(int OrderID, int UserID);
    void VerifyUserBalance(int UserID);
    void Payment(int OrderID, int UserID, int amount);
    void ConfirmOrder(int OrderID);
}

public class AddToCart : ICart
{
    public AddToCart()
    {
        Console.WriteLine("Shopping Cart Creating...");
    }

    public void AddProductToCart(int ProductID, int Qty)
    {
        Console.WriteLine("Product added to the cart.");
    }

    public void CheckProductAvailability(int ProductID)
    {
        Console.WriteLine("Product available.");
    }

    public void GetProductDetails(int ProductID)
    {
        Console.WriteLine("Product details.");
    }

    public void LockProductInStock(int ProductID, int Qty)
    {
        Console.WriteLine("Product locked in stock.");
    }
}

public class Order : IOrder
{
    public Order()
    {
        Console.WriteLine("\nOrder Creating...");
    }

    public void AddTax(int OrderID)
    {
        Console.WriteLine("Tax added.");
    }

    public void AssignAddressDetails(int OrderID, int UserID)
    {
        Console.WriteLine("Address added.");
    }

    public void ConfirmOrder(int OrderID)
    {
        Console.WriteLine("Order Confirmed");
    }

    public void Payment(int OrderID, int UserID, int amount)
    {
        Console.WriteLine("Payment Success.");
    }

    public void VerifyUserBalance(int UserID)
    {
        Console.WriteLine("User has sufficient balance.");
    }
}


// simple facade class
public interface IUserOrder
{
    void CreateCart(int ProductID, int Qty);
    void PlaceOrder(int OrderID, int UserID);
}

public class UserOrder : IUserOrder
{
    public void CreateCart(int ProductID, int Qty)
    {
        AddToCart Cart = new AddToCart();
        Cart.GetProductDetails(ProductID);
        Cart.CheckProductAvailability(ProductID);
        Cart.LockProductInStock(ProductID,Qty);
        Cart.AddProductToCart(ProductID,Qty);
    }

    public void PlaceOrder(int OrderID, int UserID)
    {
        Order order = new Order();
        order.AddTax(OrderID);
        order.AssignAddressDetails(OrderID,UserID);
        order.VerifyUserBalance(UserID);
        order.Payment(OrderID, UserID,100);
        order.ConfirmOrder(OrderID);
    }
}


// client class calling facade
class Program
{
    static void Main(string[] args)
    { 
        int ProductID = 33;
        int Quantity = 2;
        int OrderID = 10;
        int UserID = 5;

        UserOrder order = new UserOrder();
        order.CreateCart(ProductID, Quantity);
        order.PlaceOrder(OrderID,UserID);
    }
}

 

 

 

// Output
Shopping Cart Creating...
Product details.
Product available.
Product locked in stock.
Product added to the cart.

Order Creating...
Tax added.
Address added.
User has sufficient balance.
Payment Success.
Order Confirmed

In our shopping cart system, we have multiple interfaces and classes representing different parts of the system:

IUserOrder: This interface defines methods for creating a cart and placing an order.

ICart: This interface defines methods for interacting with the shopping cart, such as getting product details, checking product availability, locking products in stock, and adding products to the cart.

IOrder: This interface defines methods related to the order, like adding tax, assigning address details, verifying user balance, processing payment, and confirming the order.

The classes AddToCart and Order implement these respective interfaces and represent the complex subsystems responsible for handling the cart and order functionalities.

 

Now, here's how the Facade pattern is applied:

Facade Class (UserOrder): We create a UserOrder class that implements the IUserOrder interface. This class acts as the Facade, providing a simplified interface for the shopping cart system.

Simplified Methods: Within the UserOrder class, we implement the CreateCart and PlaceOrder methods. These methods internally handle all the complex interactions with the AddToCart and Order classes, respectively.

Client Code: From the client's perspective, they only need to interact with the UserOrder class. They don't need to know about the internal complexities of the shopping cart system.

 

The Facade pattern simplifies a complex system by providing a unified interface for clients. In the shopping cart example, the ShoppingCartFacade hides intricate operations, allowing users to create a cart and place an order without knowing the underlying complexities. It improves code readability, maintainability, and promotes loose coupling between clients and subsystems, making it an effective design pattern for managing complex systems with a user-friendly front-end.

Still you face problems, feel free to contact with me, I will try my best to help you.