本記事はGoFのデザインパターンの1つであるFactory Methodパターンについての解説と実際に実装した記事になります。 ソースコード
インスタンスを生成するメソッドを定義し、そのクラスの具象クラスにどのインスタンスを生成するかを実装させます。
これによって生成しなければならないインスタンスの種類が増えても、
このクラスの具象クラスを増やすだけですむことができます。
ユーザのIDと名前を出力するスクリプトを例にあげます。
またどの形式で出力するかをスクリプト実行時に渡します。
まず、htmlとcsv形式でユーザ情報とファイルパスを受け取って出力できるようなクラスを実装します。
class HTML(File):
def __str__(self):
return 'HTML Class'
def write(self, users, file_path):
body = self.__create_body(users)
html = f"""
<html>
<head><title>Factory Method pattern</title></head>
<body>{body}</body>
</html>
"""
with open(file_path, 'wt') as f:
f.write(html)
def __create_body(self, users):
body = """
<table>
<tr>
<th>ID</th>
<th>name</th>
</tr>
"""
for user_id, name in users:
tr = f"""
<tr>
<td>{user_id}</td>
<td>{name}</td>
</tr>
"""
body += tr
body += """
</table>
"""
return body
class CSV(File):
def __str__(self):
return 'CSV Class'
def write(self, users, file_path):
text = [['ID', 'name']]
for user_id, name in users:
user = [user_id, name]
text.append(user)
with open(file_path, 'wt') as f:
csv_out = csv.writer(f)
csv_out.writerows(text)
次にCreatorクラスを実装します。 こちらはFileオブジェクトをprintで出力した後にインスタンスを返したいとします。
ただし、どのインスタンスを返すかはまだ定まっていないので、 abstractmethodで定義し、具象クラスで実装してもらいます。
class FileCreator:
@classmethod
def create(cls):
file = cls.create_file()
print(f'created {file}')
return file
@classmethod
@abstractmethod
def create_file(cls):
pass
class HTMLCreator(FileCreator):
@classmethod
def create_file(cls):
return HTML()
class CSVCreator(FileCreator):
@classmethod
def create_file(cls):
return CSV()
クライアントはコマンドプロントから受け取ったファイルタイプ毎に Creatorをインスタンス化し、さらにそのCreatorからFileオブジェクトを生成します。
if __name__ == '__main__':
file_type = input('please input file type: ')
if file_type == 'csv':
file_path = 'test.csv'
creator = CSVCreator()
else:
file_path = 'test.html'
creator = HTMLCreator()
users = [
('001', 'Taro'),
('002', 'Jiro')
]
file = creator.create()
file.write(users, file_path)
>>> python main.py
please input file type: csv
created CSV Class
>>> python main.py
please input file type: html
created HTML Class
別のFileオブジェクトをクライアントが使いたい場合はCreatorクラスの具象クラスを増やす必要があります。