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.
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 UML class diagram (The above is quoted from Wikipedia)
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
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.
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
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")
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()
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()
-[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