TUTORIAL SERIES

Design Patterns in Python: Facade

Unified Interface

Amir Lavasani
6 min readDec 26, 2023

Have you encountered recurring coding challenges? Imagine having a toolbox of tried-and-true solutions readily available. That’s precisely what design patterns provide. In this series, we’ll explore what these patterns are and how they can elevate your coding skills.

Understanding the Facade Pattern

What is the Facade Design Pattern?

The Facade is a structural design pattern simplifying interactions within complex software systems.

It functions as a straightforward interface, shielding users from intricate inner workings while enhancing ease of use without exposing underlying complexities.

When to Use the Facade Pattern:

The Facade pattern proves crucial in software engineering for simplifying complex system interactions:

  1. Simplified Interface: Employ it for straightforward access to intricate subsystems, shielding users from complexities.
  2. Managing Complex Subsystems: Use it to streamline access to commonly used subsystem features, reducing client configuration and code.
  3. Layered Subsystem Structure: Apply it to create clear entry points in subsystem layers, reducing inter-subsystem coupling via centralized communication.

Practical Example: A Payment Facade

We’ll implement a basic Payment Facade, to streamline interactions with diverse payment gateways like PayPal, Stripe, and Crypto.

The PaymentFacade consolidates interactions with diverse gateways, offering a unified interface for payment processing and simplifying the handling of multiple methods into a cohesive solution.

Dall-E generated image with the following concept: An abstract representation of synchronized clockwork gears forming a simplified and unified mechanism

Terminology and Key Components

Its key components include:

  1. Facade Class: Acts as an entry point, directing client requests and coordinating subsystem operations.
  2. Additional Facades: Created to avoid complexity, they segregate unrelated features, making the design more manageable for clients and other facades.
  3. Complex Subsystem: Comprises various objects requiring intricate handling, abstracted by the facade to streamline their functionality.
  4. Subsystem Classes: Unaware of the facade, these classes interact directly within the system, collaborating with each other for functionality.
  5. Client: Utilizes the facade to interact with the subsystem, avoiding direct calls to its objects.
Facade design pattern structure diagram. Image from refactoring.guru

Facade Pattern Implementation in Python

This abstract implementation demonstrates the Facade pattern in Python.

Step 1: Subsystem Classes

class Subsystem1:
def operation1(self):
return "Subsystem1: Ready!"

class Subsystem2:
def operation2(self):
return "Subsystem2: Ready!"

Step 2: Implement Facade Class


class Facade:
def __init__(self):
self._subsystem1 = Subsystem1()
self._subsystem2 = Subsystem2()

def operation(self):
result = []
result.append(self._subsystem1.operation1())
result.append(self._subsystem2.operation2())
return '\n'.join(result)

Step 3: Utilize Facade in Client Code

def client_code(facade):
print(facade.operation())

# Usage
if __name__ == "__main__":
facade = Facade()
client_code(facade)

Payment Facade Implementation in Python

Below is an abstract implementation of a Payment Facade in Python, abstracting interactions with different payment gateways (PayPal, Stripe, and Crypto) into a unified interface for processing payments.

Step 1: Subsystem Classes for Payment Gateways

Represent different payment gateways, each with its payment processing method.

from abc import ABC, abstractmethod

# Step 1: Create Subsystem Classes for Payment Gateways

class PayPalGateway:
def process_payment(self, amount):
return f"Payment of ${amount} processed via PayPal"

class StripeGateway:
def pay(self, amount):
return f"Payment of ${amount} processed via Stripe"

class CryptoGateway:
def make_payment(self, amount):
return f"Payment of ${amount} processed via Crypto (Bitcoin)"

Step 2: Implement Facade Class

Initializes instances of the payment gateways and provides the process_payment() method to process payments via the selected gateway.

# Step 2: Implement Facade Class

class PaymentFacade:
def __init__(self):
self._paypal = PayPalGateway()
self._stripe = StripeGateway()
self._crypto = CryptoGateway()

def process_payment(self, amount, gateway):
"""Processes payment through the selected gateway."""
if gateway == 'paypal':
return self._paypal.process_payment(amount)
elif gateway == 'stripe':
return self._stripe.pay(amount)
elif gateway == 'crypto':
return self._crypto.make_payment(amount)
else:
return "Invalid gateway selection"

Step 3: Utilize Facade in Client Code

Demonstrates how a client utilizes the Payment Facade to process payments through different gateways using a unified interface.

# Step 3: Utilize Facade in Client Code

def main():
# Creating PaymentFacade instance
payment_facade = PaymentFacade()

# Process payments through different gateways
print(payment_facade.process_payment(100, 'paypal'))
print(payment_facade.process_payment(150, 'stripe'))
print(payment_facade.process_payment(200, 'crypto'))
print(payment_facade.process_payment(300, 'invalid_gateway'))

if __name__ == "__main__":
main()

GitHub Repo 🎉

Explore all code examples and design pattern implementations on GitHub!

10 Real-World Use Cases for Facade Pattern

These real-world applications demonstrate how the Facade pattern simplifies intricate interactions, enhancing user experience and reducing complexities in software systems.

  1. Amazon Web Services (AWS) SDK: AWS SDK’s methods abstract low-level API calls like AWS.S3.upload() for simplified cloud interactions.
  2. Django Web Framework: Django’s ORM simplifies database interactions with high-level Python objects.
  3. Git Version Control: Git commands like git commit, git push, and git pull provide a clean interface for version control without handling complex repository operations directly.
  4. Golang’s net/http package: http.Client simplifies HTTP requests by abstracting complexities like request building and response handling.
  5. TensorFlow Machine Learning Framework: TensorFlow’s Keras API simplifies building neural networks and machine learning models.
  6. Flask Web Framework: Flask’s Flask class provides a simple interface to create web applications by abstracting server configurations and routing.
  7. React JavaScript Library: React’s component-based architecture acts as a Facade, encapsulating complex DOM manipulation into reusable components.
  8. Spring Framework in Java: Spring’s JdbcTemplate offers a simplified interface for database operations, reducing the need for boilerplate code.
  9. Scikit-learn Machine Learning Library: Scikit-learn’s Pipeline class simplifies the workflow of machine learning tasks by abstracting feature extraction, transformation, and model fitting.
  10. jQuery JavaScript Library: jQuery’s methods like $().ajax() streamline DOM manipulation and AJAX requests.

Best Practices and Considerations

When implementing the Facade pattern, consider the following:

Pros and Cons

  1. Code Isolation: Facades isolate code from the complexities of subsystems, simplifying usage.
  2. God Object Risk: Facades can become overly coupled to an app’s classes, risking complexity.

Best practices

  1. Clear Abstractions: Define clear abstractions for components to maintain a consistent and understandable interface.
  2. Utilize Interfaces: Implement interfaces to ensure uniformity among different components interacting with the facade.

Considerations

  1. Complexity Management: Large hierarchical structures managed by facades might become complex to handle effectively.
  2. Runtime Efficiency: Recursive operations within the facade could impact performance, requiring optimization.
  3. Modification Challenges: Dynamically modifying the facade’s structure might pose challenges, demanding careful handling to preserve system integrity.
Dall-E generated image with the following concept: A facade-like structure composed of geometric shapes, symbolizing the orderly and simplified interface

Facade Pattern’s Relations with Other Patterns

Understanding how the Facade pattern relates to other design patterns:

Facade vs. Adapter

Facade defines a new interface for a subsystem, while Adapter makes an existing interface usable.

The Adapter usually wraps one object, while the Facade handles an entire subsystem.

Abstract Factory Comparison

Abstract Factory hides subsystem object creation from client code, offering an alternative to Facade for this purpose.

Flyweight vs. Facade

Flyweight focuses on many small objects, contrasting with Facade which represents an entire subsystem with a single object.

Facade and Mediator Similarities

Both organize collaboration between tightly coupled classes.

Facade simplifies the interface to a subsystem, while Mediator centralizes communication between system components.

Facade vs. Singleton Transformation

A Facade class can often transform into a Singleton due to its sufficiency in most cases.

Facade compared to Proxy

Both buffer complex entities, but Proxy has an interchangeable interface with its service object, unlike Facade.

Conclusion

The Facade pattern offers a simple interface, shielding users from subsystem complexities, and making software interactions more manageable.

Demonstrated in our payment gateway example, the Facade efficiently abstracts various payment gateways into a unified interface, exemplifying its practicality in handling diverse subsystems.

Hope you enjoyed the Facade pattern exploration Happy coding! 👩‍💻

Next on the Series 🚀

Read More 📜

The Series 🧭

References

  1. Design Patterns: Elements of Reusable Object-Oriented Software (Book)
  2. refactoring.guru Facade
  3. Head First Design Patterns (Book)
  4. Facade pattern
  5. sourcemaking Facade Design Pattern

--

--

Amir Lavasani

I delve into machine learning 🤖 and software architecture 🏰 to enhance my expertise while sharing insights with Medium readers. 📃