파이썬에서 디자인 패턴 "Facade"를 배우십시오.

GoF의 디자인 패턴을 학습하는 소재로서, 서적 「 증보 개정판 Java 언어로 배우는 디자인 패턴 입문 」가 참고가 되는 것 같네요. 다만, 다루어지고 있는 실례는, JAVA 베이스이기 때문에, 자신의 이해를 깊게 하기 위해서도, Python에서 동등의 프랙티스에 도전해 보았습니다.

■ Facade(파사드 패턴)



Facade 패턴 혹은 Façade 패턴(파사드 패턴)은 GoF(Gang of Four; 4명의 갱들)에 의해 정의된 컴퓨터 소프트웨어의 디자인 패턴의 하나이다. Facade(파사드)란 「건물의 정면」을 의미한다. 다른 서브시스템을 단순한 조작만을 가진 Facade 클래스로 연결해, 서브시스템간의 독립성을 높이는 것을 목적으로 한다.

UML class and sequence diagram





UML 클래스 diagram




(이상 위키피디아(Wikipedia)에서 인용)

□ 비망록



Facade 패턴은 복잡하게 얽혀서 엉망인 세부사항을 정리해, 고레벨의 인터페이스(API)를 제공한다고 합니다. Facade 역은, 시스템의 바깥쪽에 대해서는 심플한 인터페이스를 보인다고 합니다. 또, Facade역은 시스템 안쪽에 있는 각 클래스의 역할을 생각해, 올바른 순서로 클래스를 이용한다고 합니다.

그러고 보니 옛 OpenStack Heat(오케스트레이션)의 내부 구조를 조사했을 때 바로 Facade 패턴을 만난 것을 기억했습니다.
확실히, OpenStack heat-engine측에서는, SQLAlchemy 경유로 데이타베이스를 이용하고 있어, 그 데이타베이스용 세션을, 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


■ "Facade" 샘플 프로그램



실제로 Facade 패턴을 활용한 샘플 프로그램을 움직여서 다음과 같은 동작의 모습을 확인하고 싶습니다.
$ python Main.py 
welcome1.html is created for [email protected] (Hiroshi Yuki)
welcome2.html is created for [email protected] (Mamoru Takahashi)

샘플 프로그램을 시작하면 두 개의 html 파일이 생성됩니다.
각 웹 브라우저를 확인해 보면 이런 느낌이 들었습니다.
  • welcome1.html






  • welcome2.html







  • ■ 샘플 프로그램에 대해 자세히 알아보기



    Git 저장소에도 비슷한 코드가 있습니다.
    htps : // 기주 b. 이 m / 싹 / s dy_ 오 f_로 해 응 _ 파테 r
  • 디렉토리 구성
  • .
    ├── Main.py
    ├── maildata.ini
    └── pagemaker
        ├── __init__.py
        ├── database.py
        ├── html_writer.py
        └── page_maker.py
    

    (1) Facade(정면)의 역


    Facade 역은 시스템을 구성하고 있는 그 외 많은 역의 「심플한 창구」가 됩니다. Facade 역은, 고레벨로 단순한 인터페이스를 시스템 외부에 제공합니다.
    샘플 프로그램에서는, PageMaker 클래스가, 이 역할을 노력합니다.

    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) 시스템을 구성하는 다른 많은 역할



    기타 많은 역은 각각의 일을 합니다만, Facade 역은 의식하지 않습니다. Facade 역에서 불려 일을 합니다만, 그 외 많은 역으로부터 Facade 역을 호출하지 않습니다.
    샘플 프로그램에서는, Database 클래스와, HtmlWriter 클래스가, 이 역할을 노력합니다.

    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]
    hyuki@hyuki.com = Hiroshi Yuki
    hanako@hyuki.com = Hananko Sato
    tomura@hyuki.com = Tomura
    mamoru@hyuki.com = 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) Client(의뢰인)의 역할



    Facade 패턴을 이용하는 역할입니다.
    샘플 프로그램에서는, startMain 메소드가, 이 역할을 노력합니다.

    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()
    

    ■ 참고 URL


  • 「Java 언어로 배우는 디자인 패턴 입문」을 끝내고(없음)
  • Qiita 기사 "디자인 패턴 (Design Pattern) #Facade
  • 좋은 웹페이지 즐겨찾기