Learn the design pattern "Facade" with Python

As a material for learning GoF design patterns, the book "Introduction to Design Patterns Learned in the Augmented and Revised Java Language" seems to be helpful. However, since the examples taken up are based on JAVA, I tried the same practice in Python to deepen my understanding.

■ Facade (Facade pattern)

The Facade pattern or Façade pattern is one of the computer software design patterns defined by GoF (Gang of Four; 4 gangs). Facade means "the front of the building". The purpose is to connect different subsystems with a Facade class that has only simple operations, and to increase the independence between subsystems.

UML class and sequence diagram W3sDesign_Facade_Design_Pattern_UML.jpg UML class diagram Example_of_Facade_design_pattern_in_UML.png (The above is quoted from Wikipedia)

□ Memorandum

The Facade pattern is said to provide a high-level interface (API) that brings together intricately intertwined and cluttered details. The role of Facade seems to show a simple interface to the outside of the system. Also, the Facade role seems to use the classes in the correct order, considering the role of each class inside the system.

By the way, when I was investigating the internal structure of the old OpenStack Heat (orchestration), I remembered exactly when I encountered the Facade pattern. Certainly, on the OpenStack heat-engine side, the database was used via SQLAlchemy, and the sessions for that database should have been managed in the Facade pattern.

heat/heat/db/sqlalchemy/api.py


def get_facade():
    global _facade

    if not _facade:
        _facade = db_session.EngineFacade.from_config(CONF)
        if CONF.profiler.enabled:
            if CONF.profiler.trace_sqlalchemy:
                osprofiler.sqlalchemy.add_tracing(sqlalchemy,
                                                  _facade.get_engine(),
                                                  "db")

    return _facade

https://github.com/openstack/heat/blob/mitaka-eol/heat/db/sqlalchemy/api.py#L50-L61

■ "Facade" sample program

I would like to actually run a sample program that utilizes the Facade pattern and check the following behavior.

$ python Main.py 
welcome1.html is created for [email protected] (Hiroshi Yuki)
welcome2.html is created for [email protected] (Mamoru Takahashi)

When you start the sample program, two html files will be generated. When I checked each web browser, it looked like this.

page1.png
page2.png

■ Details of sample program

Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/Facade

--Directory structure

.
├── Main.py
├── maildata.ini
└── pagemaker
    ├── __init__.py
    ├── database.py
    ├── html_writer.py
    └── page_maker.py

(1) The role of Facade (front)

The Facade role is a" simple window "for many other roles that make up the system. The Facade role provides a high-level, simple interface outside the system. In the sample program, the PageMaker class serves this role.

pagemaker/page_maker.py


import sys
import json
from pagemaker.database import Database
from pagemaker.html_writer import HtmlWriter

class PageMaker(object):
    @classmethod
    def makeWelcomePage(cls, mailaddr, filename):
        try:
            prop = Database.getProperties('maildata')
            username =prop[mailaddr]
            writer = HtmlWriter(open(filename, 'w'))
            writer.title('Welcom to {}s page!'.format(username))
            writer.paragraph("We'll wait for your sending")
            writer.mailto(mailaddr, username)
            writer.close()
            print('{} is created for {} ({})'.format(filename, mailaddr, username))
        except Exception:
            print("# Failure occurred")

(2) Many other roles that make up the system

Many other roles do their jobs, but they are not aware of the Facade role. It is called by the Facade role to do the work, but many other roles do not call the Facade role. In the sample program, the Database class and the HtmlWriter class serve this role.

pagemaker/database.py


from configparser import ConfigParser

class Database(object):
    @classmethod
    def getProperties(cls, dbname):
        filename = dbname + ".ini"
        conf = ConfigParser()
        try:
            conf.read(filename)
            return conf["MailAddress"]
        except Exception:
            print("Warning: [{0}] is not found.".format(filename))

maildata.init


[MailAddress]
[email protected] = Hiroshi Yuki
[email protected] = Hananko Sato
[email protected] = Tomura
[email protected] = Mamoru Takahashi

pagemaker/html_writer.py


class HtmlWriter(object):
    def __init__(self, writer):
        self.writer = writer

    def title(self, title):
        self.writer.write("<html>\n")
        self.writer.write("<head>")
        self.writer.write("<title>{0}</title>".format(title))
        self.writer.write("</head>\n")
        self.writer.write("<body>\n")
        self.writer.write("<h1>{0}</h1>\n".format(title))

    def paragraph(self, msg):
        self.writer.write("<p>{0}</p>\n".format(msg))

    def link(self, href, caption):
        self.writer.write("<a href=\"{0}\">{1}</a>".format(href, caption))

    def mailto(self, mailaddr, username):
        self.link("mailto:{0}".format(mailaddr), username)

    def close(self):
        self.writer.write("</body>\n")
        self.writer.write("</html>\n")
        self.writer.close()

(3) The role of Client

It is a role to use the Facade pattern. In the sample program, the startMain method serves this role.

Main.py


from pagemaker.page_maker import PageMaker

def startMain():
    PageMaker.makeWelcomePage("[email protected]", "welcome1.html")
    PageMaker.makeWelcomePage("[email protected]", "welcome2.html")

if __name__ == '__main__':
    startMain()

■ Reference URL

-[Finishing "Introduction to Design Patterns Learned in Java Language" (Not)](https://medium.com/since-i-want-to-start-blog-that-looks-like-men-do/java Introduction to Design Patterns Learned in Language-Finishing-Not-2cc9b34a30b2) -Qiita article "Design Pattern #Facade

Recommended Posts

Learn the design pattern "Facade" with Python
Learn the design pattern "Singleton" with Python
Learn the design pattern "Prototype" in Python
Learn the design pattern "Builder" in Python
Learn the design pattern "Flyweight" in Python
Learn the design pattern "Observer" in Python
Learn the design pattern "Memento" in Python
Learn the design pattern "Command" in Python
Learn the design pattern "Visitor" in Python
Learn the design pattern "Bridge" in Python
Learn the design pattern "Mediator" in Python
Learn the design pattern "Decorator" in Python
Learn the design pattern "Iterator" in Python
Learn the design pattern "Strategy" in Python
Learn the design pattern "Composite" in Python
Learn the design pattern "State" in Python
Learn the design pattern "Adapter" in Python
Learn the design pattern "Abstract Factory" in Python
Learn the design pattern "Template Method" in Python
Learn the design pattern "Factory Method" in Python
Learn the design pattern "Chain of Responsibility" in Python
Design Pattern #Facade
Learn Python with ChemTHEATER
Learn the design pattern "Singleton" with Python
Learn the design pattern "Facade" with Python
Learn Nim with Python (from the beginning of the year).
The first algorithm to learn with Python: FizzBuzz problem
Python Design Pattern --Template method
Learn search with Python # 2bit search, permutation search
Get the weather with Python requests
Get the weather with Python requests 2
Hit the Etherpad-lite API with Python
Install the Python plugin with Netbeans 8.0.2
Master the type with Python [Python 3.9 compatible]
Learn the basics of Python ① Beginners
Let's utilize the design pattern like C language with OSS design_pattern_for_c!
Design patterns to enjoy with frequently used Java libraries --Facade pattern
Make the Python console covered with UNKO
Getting Started with python3 # 1 Learn Basic Knowledge
Behind the flyer: Using Docker with Python
Learn the basics while touching python Variables
Check the existence of the file with python
[Python] Drawing a swirl pattern with turtle
GoF design pattern from the problem 2. Structure
[Python] Get the variable name with str
Search the maze with the python A * algorithm
Working with OpenStack using the Python SDK
[Gang of Four] Design pattern learning --Facade
Download files on the web with Python
GoF design pattern from the problem 1. Generation
[Python] Automatically operate the browser with Selenium
Intuitively learn the reshape of Python np
The road to compiling to Python 3 with Thrift
GoF design pattern from the problem 3. Behavior
I tried "smoothing" the image with Python + OpenCV
FizzBuzz with Python3
Scraping with Python
[Python] Get the files in a folder with Python
Load the network modeled with Rhinoceros in Python ③
Prepare the execution environment of Python3 with Docker
Statistics with python
Design Pattern #Builder