Pythonで学ぶデザインパターン入門 Factory Methodパターン
結城先生の Java言語で学ぶデザインパターン入門
のコードを Python に書き直していくシリーズ第4段です。
Factory Methodパターンとは
前回紹介した
を、インスタンス生成の際の肉付けという特定パターンで活用したものです。
つまり、サブクラスでインスタンスを生成します。
ソースコード
コードの概要
ざっくりと言うとIDカードを作成するといったコードになります。
スーパークラスに、frameworkパッケージとしてインスタンス生成を担当する Factory
クラス と生成される Product
クラスが存在します。
それぞれにスーパークラスをIDカードにおける肉付けをして継承したクラスがidcardパッケージとして存在します。
ソースコード
Product
# coding: utf-8 from abc import ABCMeta, abstractmethod class Product(metaclass=ABCMeta): @abstractmethod def use(self): pass
Factory
# coding: utf-8 from abc import ABCMeta, abstractmethod from factory_method.framework.product import Product class Factory(metaclass=ABCMeta): def create(self, owner: str) -> Product: p = self.create_product(owner) self.register_product(p) return p @abstractmethod def create_product(self, owner: str) -> Product: pass @abstractmethod def register_product(self, product: Product): pass
インスタンスを返すメソッドだけ決め打ちで処理を生成してしまって、あとはサブクラスに任せます。
IDCard (Productを継承)
# coding: utf-8 from factory_method.framework.product import Product class IDCard(Product): def __init__(self, owner: str): print('%sのカードを作ります。' % owner) self.__owner = owner def use(self): print('%sのカードを使います。' % self.__owner) def get_owner(self) -> str: return self.__owner
IDCardFactory(Factoryを継承)
# coding: utf-8 from factory_method.framework.factory import Factory from factory_method.framework.product import Product from factory_method.idcard.id_card import IDCard class IDCardFactory(Factory): def __init__(self): self.__owners = [] def create_product(self, owner: str) -> Product: return IDCard(owner) def register_product(self, product: Product): product.__class__ = IDCard self.__owners.append(product.get_owner()) def get_owners(self) -> list: return self.__owners
Factoryを継承したこのサブクラスで具体的にどのクラスのインスタンスを作成するかを指定します。
実行ファイル
# coding: utf-8 from factory_method.idcard.id_card_factory import IDCardFactory if __name__ == '__main__': factory = IDCardFactory() card1 = factory.create('さるへい') card2 = factory.create('へいさる') card3 = factory.create('たかし') card1.use() card2.use() card3.use()
実際どう便利か
ポイントは、Factoryはサブクラスで具体的にどのインスタンスが生成されるかはわからないということです。
Factoryクラスはサブクラスの存在を一切気にする必要がありません。よってこの抽象クラスを使い回すことができます。
インスタンス生成の定形パターンがあった際などは、Factory Methodパターンを用いてコードの重複を排除できたりするのでおすすめです。