Facade Pattern provides a unified and simple interface over a complex set of classes in a system, thus making the system easier to use.
Consider a Grocery shop. Where items are organized with an inventory management system. But, the customer need not know about the inventory, so it’s preferable that the customer must ask the shopkeeper with the list of items, as the shopkeeper knows where each item is located. Here the shopkeeper is serving as the Facade interface.
Customers need the items but they don’t know about inventory(Complex sub-systems), so there is a shopkeeper (A simple interface) who searches the items on behalf of customers.
The word Facade referred to an outer lying interface of a complex system, consists of several sub-systems.
In short, Facade Pattern suggests defining a facade interface that should mask the complexity of the underlying system and should access the system on behalf of a client, hiding the implementation detail.
Facade Patterns helps:
- To make a complex subsystem easier to use.
- And, to minimize the dependencies between sub-systems.
Clients that access a complex subsystem directly, develop some tight coupling(dependencies), which makes the clients hard to implement, change, test, and reuse.
The three components of the Facade Pattern:
- System class – The sub-systems having complexity.
- Facade class – Unified and user-friendly interface.
- Client class – Classes that use Facade class to access functionality of system.
Customers call the pizza shop to place an order. Then the pizza is prepared by the chef. And, then pizza is delivered to the customer. So there are several subtasks from preparing to delivery of the pizza. All these three steps are like three sub-system classes.
We need a composite system that automates the whole task. Here we will require a Facade method that will work as an operator for all our services(sub-tasks). So let’s implement these sub-system classes first.
TakeOrderclass to place an order.
class TakeOrder: def order(self): print("Getting the order.")
CookPizzaclass to prepare the Pizza
class CookPizza: def prepare(self): print("Preparing the Pizza...")
Deliveryclass to deliver the Pizza
class Delivery: def deliver(self): print("Delivered the Pizza.")
Operatorclass serving as Facade Interface, automating the whole procedure.
class Operator: '''Facade Interface''' def __init__(self): self.ordering = TakeOrder() self.preparing = CookPizza() self.delivering = Delivery() def completeOrder(self): self.ordering.order() self.preparing.prepare() self.delivering.deliver() print("Order completed successfully.")
The client needs to initiate the
Operator class and call
completeOrder method and have no need to know how all internal processes work. Full implementation will look like this:
#Subsystem 1 class TakeOrder: def order(self): print("Getting the order.") #Subsystem 2 class CookPizza: def prepare(self): print("Preparing the Pizza...") #Subsystem 3 class Delivery: def deliver(self): print("Delivered the Pizza.") class Operator: '''Facade Interface''' def __init__(self): self.ordering = TakeOrder() self.preparing = CookPizza() self.delivering = Delivery() def completeOrder(self): self.ordering.order() self.preparing.prepare() self.delivering.deliver() print("Order completed successfully.") """ main method """ if __name__ == "__main__": op = Operator() op.completeOrder()
The output will be like this:
Getting the order. Preparing the Pizza... Delivered the Pizza. Order completed successfully.
Pros and Cons of the Facade Design Pattern
- Facade Pattern easily isolates our code from the complexity of a subsystem.
- Helps to loose-couple the entities(i.e. sub-systems and client), upholding Dependency Inversion Principle.
- Changes to the sub-system may lead the changes to the Facade interface.
- Facade Interface object can become a supreme object coupled to all classes of an app.