add facade code example

This commit is contained in:
Ruidy 2020-09-27 14:26:34 +02:00
parent 7114a08dac
commit a46fcbfdc6
8 changed files with 118 additions and 0 deletions

View file

@ -14,3 +14,4 @@
- [Adapter](structural/adapter/README.md)
- [Bridge](structural/bridge/README.md)
- [Composite](structural/composite/README.md)
- [Facade](structural/facade/README.md)

View file

@ -5,3 +5,4 @@ Structural patterns explain how to assemble objects and classes into larger stru
- [Adapter](adapter/README.md)
- [Bridge](bridge/README.md)
- [Composite](composite/README.md)
- [Facade](facade/README.md)

0
structural/__init__.py Normal file
View file

View file

@ -0,0 +1,32 @@
# Facade Pattern
Facade is a structural design pattern that provides a simplified (but limited) interface to a complex system of classes, library or framework.
## Summary
Facade is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes.
## Problem
Imagine that you must make your code work with a broad set of objects that belong to a sophisticated library or framework. Ordinarily, youd need to initialize all of those objects, keep track of dependencies, execute methods in the correct order, and so on.
As a result, the business logic of your classes would become tightly coupled to the implementation details of 3rd-party classes, making it hard to comprehend and maintain.
## Solution
A facade is a class that provides a simple interface to a complex subsystem which contains lots of moving parts. A facade might provide limited functionality in comparison to working with the subsystem directly. However, it includes only those features that clients really care about.
Having a facade is handy when you need to integrate your app with a sophisticated library that has dozens of features, but you just need a tiny bit of its functionality.
For instance, an app that uploads short funny videos with cats to social media could potentially use a professional video conversion library. However, all that it really needs is a class with the single method `encode(filename, format)`. After creating such a class and connecting it with the video conversion library, youll have your first facade.
## How to Implement
1. Check whether its possible to provide a simpler interface than what an existing subsystem already provides. Youre
on the right track if this interface makes the client code independent from many of the subsystems classes.
1. Declare and implement this interface in a new facade class. The facade should redirect the calls from the client code to appropriate objects of the subsystem. The facade should be responsible for initializing the subsystem and managing its further life cycle unless the client code already does this.
1. To get the full benefit from the pattern, make all the client code communicate with the subsystem only via the facade. Now the client code is protected from any changes in the subsystem code. For example, when a subsystem gets upgraded to a new version, you will only need to modify the code in the facade.
1. If the facade becomes too big, consider extracting part of its behavior to a new, refined facade class

View file

View file

@ -0,0 +1,36 @@
from structural.facade.subsystems import Subsystem1, Subsystem2
class Facade:
"""
The Facade class provides a simple interface to the complex logic of one or
several subsystems. The Facade delegates the client requests to the
appropriate objects within the subsystem. The Facade is also responsible for
managing their lifecycle. All of this shields the client from the undesired
complexity of the subsystem.
"""
def __init__(self, subsystem1: Subsystem1, subsystem2: Subsystem2) -> None:
"""
Depending on your application's needs, you can provide the Facade with
existing subsystem objects or force the Facade to create them on its
own.
"""
self._subsystem1 = subsystem1 or Subsystem1()
self._subsystem2 = subsystem2 or Subsystem2()
def operation(self) -> str:
"""
The Facade's methods are convenient shortcuts to the sophisticated
functionality of the subsystems. However, clients get only to a fraction
of a subsystem's capabilities.
"""
results = []
results.append("Facade initializes subsystems:")
results.append(self._subsystem1.operation1())
results.append(self._subsystem2.operation1())
results.append("Facade orders subsystems to perform the action:")
results.append(self._subsystem1.operation_n())
results.append(self._subsystem2.operation_z())
return '\n'.join(results)

24
structural/facade/main.py Normal file
View file

@ -0,0 +1,24 @@
from structural.facade.facade import Facade
from structural.facade.subsystems import Subsystem1, Subsystem2
def client_code(facade: Facade) -> None:
"""
The client code works with complex subsystems through a simple interface
provided by the Facade. When a facade manages the lifecycle of the
subsystem, the client might not even know about the existence of the
subsystem. This approach lets you keep the complexity under control.
"""
print(facade.operation(), end='')
if __name__ == '__main__':
# The client code may have some of the subsystem's objects already created.
# In this case, it might be worthwhile to initialize the Facade with these
# objects instead of letting the Facade create new instances.
subsystem1 = Subsystem1()
subsystem2 = Subsystem2()
facade = Facade(subsystem1, subsystem2)
client_code(facade)

View file

@ -0,0 +1,24 @@
class Subsystem1:
"""
The Subsystem can accept requests either from the facade or client directly.
In any case, to the Subsystem, the Facade is yet another client, and it's
not a part of the Subsystem.
"""
def operation1(self) -> str:
return "Subsystem1: Ready!"
def operation_n(self) -> str:
return "Subsystem1: Go!"
class Subsystem2:
"""
Some facades can work with multiple subsystems at the same time.
"""
def operation1(self) -> str:
return "Subsystem2: Get ready!"
def operation_z(self) -> str:
return "Subsystem2: Fire!"