En tant que matériel d'apprentissage des modèles de conception du GoF, le livre «Introduction aux modèles de conception appris dans le langage Java augmenté et révisé» semble être utile. Cependant, comme les exemples repris sont basés sur JAVA, j'ai essayé la même pratique avec Python pour approfondir ma compréhension.
Le modèle de façade ou modèle de façade est l'un des modèles de conception de logiciels informatiques définis par le GoF (Gang of Four; 4 gangs). Façade signifie «la façade du bâtiment». Le but est de connecter différents sous-systèmes avec une classe Facade qui n'a que des opérations simples, et d'augmenter l'indépendance entre les sous-systèmes.
UML class and sequence diagram UML class diagram (Ce qui précède est cité sur Wikipedia)
On dit que le motif de façade fournit une interface de haut niveau (API) qui rassemble des détails intimement entrelacés et encombrés. Le rôle de Facade semble montrer une interface simple vers l'extérieur du système. De plus, le rôle Facade semble utiliser les classes dans le bon ordre, compte tenu du rôle de chaque classe à l'intérieur du système.
Au fait, lorsque j'étudiais la structure interne de l'ancien OpenStack Heat (orchestration), je me suis juste souvenu que je suis tombé sur le modèle Facade
.
Certes, du côté du moteur thermique OpenStack, la base de données a été utilisée via SQLAlchemy, et les sessions de cette base de données auraient dû être gérées dans le modèle Facade
.
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
Je voudrais exécuter un exemple de programme qui utilise le modèle de façade et vérifier le comportement suivant.
$ python Main.py
welcome1.html is created for [email protected] (Hiroshi Yuki)
welcome2.html is created for [email protected] (Mamoru Takahashi)
Lorsque vous démarrez l'exemple de programme, deux fichiers html seront générés. Lorsque j'ai vérifié chacun des navigateurs Web, cela ressemblait à ceci.
Un code similaire a été téléchargé dans le référentiel Git. https://github.com/ttsubo/study_of_design_pattern/tree/master/Facade
.
├── Main.py
├── maildata.ini
└── pagemaker
├── __init__.py
├── database.py
├── html_writer.py
└── page_maker.py
Le rôle «Façade» est une «fenêtre simple» pour de nombreux autres rôles qui composent le système. Le rôle «Façade» fournit une interface simple et de haut niveau en dehors du système.
Dans l'exemple de programme, la classe PageMaker
remplit ce rôle.
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")
De nombreux autres rôles font leur travail, mais ils ne sont pas conscients du rôle «Façade». Il est appelé par le rôle «Façade» pour faire le travail, mais de nombreux autres rôles n'appellent pas le rôle «Façade».
Dans l'exemple de programme, la classe Database
et la classe HtmlWriter
remplissent ce rôle.
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()
C'est un rôle d'utiliser le modèle de façade.
Dans l'exemple de programme, la méthode startMain
remplit ce rôle.
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()
Recommended Posts