Als Material zum Erlernen von GoF-Entwurfsmustern scheint das Buch "Einführung in Entwurfsmuster, die in der erweiterten und überarbeiteten Java-Sprache gelernt wurden" hilfreich zu sein. Da die aufgeführten Beispiele jedoch auf JAVA basieren, habe ich dieselbe Vorgehensweise mit Python versucht, um mein Verständnis zu vertiefen.
Das Fassadenmuster oder Fassadenmuster ist eines der von GoF (Gang of Four; 4 Banden) definierten Entwurfsmuster für Computersoftware. Fassade bedeutet "die Vorderseite des Gebäudes". Der Zweck besteht darin, verschiedene Subsysteme mit einer Facade-Klasse zu verbinden, die nur einfache Operationen aufweist, und die Unabhängigkeit zwischen Subsystemen zu erhöhen.
UML class and sequence diagram UML class diagram (Das Obige wird aus Wikipedia zitiert)
Das Fassadenmuster soll eine High-Level-Schnittstelle (API) bieten, die komplex miteinander verflochtene und überfüllte Details zusammenführt. Die Rolle der Fassade scheint eine einfache Schnittstelle zur Außenseite des Systems zu zeigen. Außerdem scheint die Fassadenrolle die Klassen in der richtigen Reihenfolge zu verwenden, wenn man die Rolle jeder Klasse innerhalb des Systems berücksichtigt.
Übrigens, als ich die interne Struktur der alten OpenStack Heat (Orchestrierung) untersuchte, fiel mir nur ein, dass ich auf das "Fassaden" -Muster gestoßen war. Auf der OpenStack-Wärmekraftmaschinenseite wurde die Datenbank sicherlich über SQLAlchemy verwendet, und die Sitzungen für diese Datenbank sollten im "Fassaden" -Muster verwaltet worden sein.
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
Ich möchte tatsächlich ein Beispielprogramm ausführen, das das Fassadenmuster verwendet, und das folgende Verhalten überprüfen.
$ python Main.py
welcome1.html is created for [email protected] (Hiroshi Yuki)
welcome2.html is created for [email protected] (Mamoru Takahashi)
Wenn Sie das Beispielprogramm starten, werden zwei HTML-Dateien generiert. Als ich jeden Webbrowser überprüfte, sah es so aus.
Ähnlicher Code wurde in das Git-Repository hochgeladen. https://github.com/ttsubo/study_of_design_pattern/tree/master/Facade
--Verzeichnisaufbau
.
├── Main.py
├── maildata.ini
└── pagemaker
├── __init__.py
├── database.py
├── html_writer.py
└── page_maker.py
Die Rolle "Fassade" ist ein "einfaches Fenster" für viele andere Rollen, aus denen das System besteht. Die Rolle "Fassade" bietet eine einfache Schnittstelle auf hoher Ebene außerhalb des Systems. Im Beispielprogramm übernimmt die PageMaker-Klasse diese Rolle.
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")
Viele andere Rollen erledigen ihre Arbeit, aber sie kennen die Rolle "Fassade" nicht. Es wird von der Rolle "Fassade" aufgerufen, die Arbeit zu erledigen, aber viele andere Rollen nennen die Rolle "Fassade" nicht. Im Beispielprogramm übernehmen die Klasse "Database" und die Klasse "HtmlWriter" diese Rolle.
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()
Es ist eine Rolle, das Fassadenmuster zu verwenden. Im Beispielprogramm übernimmt die Methode "startMain" diese Rolle.
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