PythonでFactory methodの実装方法をまとめます。
この記事を大きく参考にしている。
使いどころ
既存の実装を修正せずに新しい機能を実装し、従来と同じ関数から使用したいとき
- メリット
- 既存の実装を変えずにコードを追加していくだけで機能を追加できる
- デメリット
- 設計の複雑化
- 実装コストが高い
サンプル
今回、理解度をあげるためにサンプルコードを作ります。
雑仕様
ビールの名前を指定するとそのビールのインスタンスが作られる。
>>> asahi = create_beer("asahi")
Created Asahi beer!
>>> ichibann = create_beer("ichibann_shibori")
Created Ichiban shibori beer!
モジュール図
処理を追加したいとき(新しいビールの作成方法を追加するとき)
以下のように追加したい関数に対して、_registry.py
のregister_beer()
をデコレータとして追記します。
@register_beer
def custom_beer():
pass
register_beer()
では、内部の辞書(_beer_entry_points
)を呼び出し、関数名から関数を引けるように作ります。
# 辞書の例
_beer_entry_points = {"sapporo" : sapporo_beer}
所望の処理を呼び出したいとき(ビールのインスタンスを作成するとき)
以下のように名前を指定するだけで、ビールのインスタンスが作成できます。
>>> asahi = create_beer("asahi")
create_beer()
では、内部の辞書(_beer_entry_points
)に登録された関数を呼びだしています。
def create_beer(beer_name):
# beer_entry_point()では内部辞書にアクセスし、
# 名前から関数を取得
fn = beer_entry_point(beer_name)
# 関数を実行し、インスタンス化
return fn()
呼び出される関数は以下のようにインスタンス化するように実装しておきます。
class Asahi:
def __init__(self):
print("Created Asahi beer!")
@register_beer
def asahi_beer():
# インスタンス化
return Asahi()
終わりに
デザインパターンを知ると無理やりでも使いたくなります。その場合、時間だけが増えていってしまい、慣れてないうちは危険かもしれないと感じました。
ソースは以下に起きました。