Facade Pattern

Introduction:

Facade is a structural design pattern. The objective of the facade design pattern is to provide the simple interface to a complex subsystem. Wraps a complicated sub system with a simple interface. It promotes decoupling subsystem from its clients . On the other hand,  facade is the only access point for the subsystem.

when to use, 

A segment of the client community needs a simplified interface to the overall functionality of a complex subsystem.





How to use,

  1. Identify a simpler, unified interface for the subsystem or component.
  2. Design a “wrapper” class that encapsulates the subsystem.
  3. The facade/wrapper captures the complexity and collaborations of the component, and delegates to the appropriate methods.
  4. The client uses (is coupled to) the Façade only.
  5. Consider whether additional Facades would add value.

How Facade is different from other similar patterns, 

Adapter vs Facade:
Facade provides a new interface, whereas adapter uses an existing interfaces (that means it make two existing interfaces to work together).

Mediator vs Facade:
Mediator centralizes communications between objects. It routinely adds value, and it is known/referenced by the colleagues objects.  In contrast, facade defines a simpler interface to a subsystem, it doesn't add any functionality. It isn't known by the subsystem classes.

Example:

Design a customer service representative. The customer calls to a customer service representative to place a order from catalog.  Customer service representative acts as a facade and providing interface for order placing system, billing system, delivery system.

Implementation:

Sourcecode: https://github.com/krishnaKSA/design_patterns_cplusplus/blob/main/FacadePattern/FacadePattern.hpp

UML Class diagram:





















//Order class
class Order
{
  public:
  void placeOrder()
  {
     cout<<"Order::order placed "<<endl;
  }
};

//Payment class
class Payment
{
   public:
   void payBill()
   {
     cout<<"Payment::Payment done "<<endl;
  }
};

//Delivery class
class Delivery
{
   public:
  void deliverOrder()
   {
     cout<<"Delivery::Delivery completed "<<endl;
   }
};

Facade class:

//Facade class
    class Facade
    {
        private:
        //Facade holds the objects of subsystems
        Order *order_obj;
        Payment *payment_obj;
        Delivery *delivery_obj;

        public:
        Facade(Order* oObj=nullptr, Payment* pObj=nullptr, Delivery* dObj=nullptr)
        {
            order_obj = oObj;
            payment_obj = pObj;
            delivery_obj = dObj;
        }

        //customer service function
        void customerService()
        {
            bool bRetValue = false;
            if(nullptr != order_obj)
            {
                order_obj->placeOrder();

                if(nullptr != payment_obj)
                {
                    payment_obj->payBill();

                    if(nullptr != delivery_obj)
                    {
                        delivery_obj->deliverOrder();
                        bRetValue = true;
                    }
                }
            }
            if(!bRetValue)
            {
                cout<<"Facade::CustomerService :: Couldn't able to place the order !!!"<<endl;
            }
            else
            {
                cout<<"Facade::CustomerService :: Order placed successfully !!!"<<endl;
            }
        }
    };

Client code:

    void testFacadePattern()
    {
        Facade* obj = new Facade(new Order, new Payment, new Delivery);
        obj->customerService();
    }