🐕
Builderパターンを学ぶ【Python】
一言で言うと
複雑な処理をDirectorクラスに隠蔽することによって交換可能性を高めることができる。
コードサンプル
ディレクトリ構造
builder
├── builder.py
├── director.py
├── html_builder.py
├── main.py
└── text_builder.py
main.py
import sys
from director import Director
from html_builder import HtmlBuilder
from text_builder import TextBuilder
def main(args: list[str]) -> None:
if args[1] == 'plain':
text_builder: TextBuilder = TextBuilder()
director: Director = Director(text_builder)
director.construct()
print(text_builder.get_result())
elif args[1] == 'html':
html_builder: HtmlBuilder = HtmlBuilder()
director: Director = Director(html_builder)
director.construct()
print(f'{html_builder.get_result()}が作成されました。')
else:
usage()
exit(0)
def usage() -> None:
print('Usage: python plain プレーンテキストで文書を作成')
print('Usage: python html HTMLファイルで文書を作成')
pass
if __name__ == '__main__':
args = sys.argv
# print(args)
# > ['main.py', 'plain']
if len(args) != 2:
usage()
exit(0)
main(args)
director.py
from builder import Builder
class Director():
def __init__(self, builder: Builder) -> None:
self.builder: Builder = builder
def construct(self) -> None:
self.builder.make_title('Greeting')
self.builder.make_string('朝から昼にかけて')
self.builder.make_items(['おはようございます', 'こんにちは'])
self.builder.make_string('夜に')
self.builder.make_items(['こんばんは', 'おやすみなさい', 'さようなら'])
self.builder.close()
builder.py
from abc import ABCMeta, abstractmethod
class Builder(metaclass=ABCMeta):
@abstractmethod
def make_title(self, title: str) -> None:
pass
@abstractmethod
def make_string(self, str: str) -> None:
pass
@abstractmethod
def make_items(self, items: list[str]) -> None:
pass
@abstractmethod
def close(self) -> None:
pass
director.py
from builder import Builder
class Director():
def __init__(self, builder: Builder) -> None:
self.builder: Builder = builder
def construct(self) -> None:
self.builder.make_title('Greeting')
self.builder.make_string('朝から昼にかけて')
self.builder.make_items(['おはようございます', 'こんにちは'])
self.builder.make_string('夜に')
self.builder.make_items(['こんばんは', 'おやすみなさい', 'さようなら'])
self.builder.close()
html_builder.py
import io
from builder import Builder
class HtmlBuilder(Builder):
def make_title(self, title: str):
self.__file_name = f'{title}.html'
self.__file: io.TextIOWrapper = io.open(self.__file_name, 'w',
encoding='utf-8', newline='\n')
self.__file.write(
f'<html><head><title>{title}</title></head></body>\n')
self.__file.write(f'<h1>{title}</h1>\n')
def make_string(self, str: str) -> None:
self.__file.write(f'<p>{str}</p>\n')
def make_items(self, items: list[str]) -> None:
self.__file.write('<ul>\n')
for item in items:
self.__file.write(f'<li>{item}</li>\n')
self.__file.write('</ul>\n')
def close(self) -> None:
self.__file.write('</body></html>\n')
self.__file.close()
def get_result(self) -> str:
return self.__file_name
text_builder.py
from builder import Builder
class TextBuilder(Builder):
__str_buf: list = []
def make_title(self, title: str):
self.__str_buf.append('===============================')
self.__str_buf.append(f'『{title}』')
self.__str_buf.append('')
def make_string(self, str: str) -> None:
self.__str_buf.append(f'■{str}')
self.__str_buf.append('')
def make_items(self, items: list[str]) -> None:
for item in items:
self.__str_buf.append(f' ・{item}')
self.__str_buf.append('')
def close(self) -> None:
self.__str_buf.append('===============================')
def get_result(self) -> str:
return '\n'.join(self.__str_buf)
Discussion