nonoのポートフォリオサイト

デザインパターン abstract_factory

デザインパターンの一つであるAbstract Pattern

abstract_factoryパターンは、共通性のある部品をあらかじめ作成しておき再利用します。


イメージ

エンジンインターフェース

  1. スポーツカーのエンジン
  2. 軽自動車のエンジン

タイヤインターフェース

  1. スポーツカーのタイヤ
  2. 軽自動車のタイヤ

サンプルコード

abstract_factoryの抽象的クラスをabstract_factory.pyとして以下のように作成します。HTMLを生成するロジックです。


from abc import ABC, abstractmethod

# 各製品の部品を生成するための、継承先となる抽象クラス(Product)
class AbcItem(ABC):

    def __init__(self, caption):
        self.caption = caption

    @abstractmethod
    def make_html(self):
        pass


class PageItem(AbcItem):

    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.content = []

    def add(self, item):
        self.content.append(item)

    def write_html(self, file_name):
        with open(file_name, 'w', encoding='utf-8') as fh:
            fh.write(self.make_html())


class LinkItem(AbcItem):
    """"""
    def __init__(self, caption, url):
        super().__init__(caption)
        self.url = url


class ListItem(AbcItem):
    """ 
  • """ def __init__(self, caption): super().__init__(caption) self.items = [] def add(self, item): self.items.append(item) # Productを生成する Factory の定義 class Factory(ABC): @abstractmethod def create_page_item(self, title, author): pass @abstractmethod def create_link_item(self, caption, url): pass @abstractmethod def create_list_item(self, caption): pass

    abstract_factory.pyを継承して、contract_factory.pyで具体的なロジックを作成する

    
    # concrete_factory.py
    from abstract_factory import(
        LinkItem, ListItem, PageItem, Factory
    )
    
    
    class HtmlPateItem(PageItem):
    
        def __init__(self, title, author):
            super().__init__(title, author)
    
        #abstractmethodの具体化
        def make_html(self):
            output = f'<html>\n<head>\n<title>{self.title}' \
                     f'</title>\n</head>\n'
            output += f'<body>\n'
            output += f'<h1>{self.title}</h1>\n'
            output += f'<ul>'
            for list_item in self.content:
                output += list_item.make_html()
            output += f'</ul>\n'
            output += f'<hr>\n<address>{self.author}</address>\n'
            output += '</body></html>'
    
            return output
    
    
    class HtmlLinkItem(LinkItem):
    
        def __init__(self, caption, url):
            super().__init__(caption, url)
    
        def make_html(self):
            return f'<li><a href="{self.url}">{self.caption}</a></li>'
    
    
    class HtmlListItem(ListItem):
        """ link item を入れる """
        def __init__(self, caption):
            super().__init__(caption)
    
        def make_html(self):
            output = '<li>\n'
            output += self.caption + '\n'
            output += '<ul>\n'
            for link_item in self.items:
                output += link_item.make_html()
            output += '</ul>\n'
            output += '</li>\n'
    
            return output
    
    
    # ConcreteProductを生成する ConcreteFactory
    class HtmlFactory(Factory):
    
        def create_page_item(self, title, author):
            return HtmlPateItem(title, author)
    
        def create_link_item(self, caption, url):
            return HtmlLinkItem(caption, url)
    
        def create_list_item(self, caption):
            return HtmlListItem(caption)
    
    
    if __name__ == '__main__':
    
        html_factory = HtmlFactory()
    
        asahi = html_factory.create_link_item('Asahi News Paper', 'http://asahi')
        yomiuri = html_factory.create_link_item('Yomiuri news paper', 'http://yomiuri')
        yahoo = html_factory.create_link_item('Yahoo', 'http://yahoo')
        google = html_factory.create_link_item('Google', 'http://google')
        wikipedia = html_factory.create_link_item('Wikipedia', 'http://wikipedia')
    
        news_pages = html_factory.create_list_item('News Paper')
        news_pages.add(asahi)
        news_pages.add(yomiuri)
    
        other_pages = html_factory.create_list_item('Other pages')
        other_pages.add(yahoo)
        other_pages.add(google)
        other_pages.add(wikipedia)
    
        all_page = html_factory.create_page_item('My Page', 'Taro')
        all_page.add(news_pages)
        all_page.add(other_pages)
    
        all_page.write_html('tmp.html')