LoginSignup
1
4

More than 3 years have passed since last update.

駆け出しpythonエンジニアのまとめ デザインパターンまとめ1(abstract factory)

Last updated at Posted at 2021-05-04

趣旨

駆け出しエンジニアの備忘録の垂れ流し。
 ※ 出典漏れがあればご指摘ください

出典:
https://yamakatsusan.web.fc2.com/pythonpattern08.html
https://dackdive.hateblo.jp/entry/python-design-pattern/abstract-factory
https://www.oreilly.co.jp/books/9784873117393/

abstract factoryパターン概要

生成方法がほぼ同様の手順で、かつ、複数のクラスのインスタンス(Product)の生成が発生するようなドメインの実装をするにあたり、Factoryクラスを作ることで、生成処理の実装をシンプルに、かつclient側から作成の責務を分離する。
Productクラスのインスタンスの生成にあたり、Clientに生成するためのインターフェースを提供するFactoryクラスを実装する。Factoryクラスはお手本となるAbstract Factoryに則った実装となる。
Clientの関心事は部品を使うことであり、どんな部品であっても作ることはFactoryに任せることが可能となる。
(Clientは、具象Factoryを指定し、生成のためのインターフェースを呼び出すだけで良い)

クラス図とシーケンス図

クラス

W3sDesign_Abstract_Factory_Design_Pattern_UML.jpg

wikipediaより引用

実装方針

  • AbstractFactoryクラスではtemplate methodのようにProductインスタンス作成手順(必須メソッド)を規定する。
  • Factoryサブクラスでは必須メソッドをオーバーライドする。
  • ClientではFactoryサブクラスを呼び出し(生成し)、インターフェースを呼び出す処理を実装する
  • Client側では呼び出すFactoryクラスの指定が必要。Factoryクラスを決定するメソッドがAbstractFactoryクラスにあると便利。これは@classmethodを利用して実現可能。また、Factoryクラスインスタンスの生成をしないで、productインスタンスの生成が行えるようになる。
    • classmethodの用法の1つに、自身のインスタンスを生成する手段としての用法がある。
    • 応用として、どのクラスのインスタンスを生成するか決定するロジックをもたせることで、 AbstractFactoryのみの指定で、具象factoryのimportを不要とすることも可能。
実装例1
# factory側
class AbstractFactory:
 @abstractmethod
 def create_product1(self):
   pass
 @abstractmethod
 def create_product2(self):
   pass
 @classmethod
 def get_factory(cls, some_args):
     selected_class = get_class(some_args)  # クラスを指定するロジックを記載

     return selected_class()

class FactoryA(AbstractFactory):
 def create_product1(self):
   # 実処理を記載
   return Product1A()
 def create_product2(self):
   # 実処理を記載
   return Product2A()

# client側
def main():
 factory =  AbstractFactory.get_factory(choose_some_keywords_for_selecting_cls)
 product_1  = factory.create_product1()
 product_2  = factory.create_product2() 

実装例2
# class内クラスにproductクラスを記載するパターン
# 生成するProductが簡単ならこちらでもOK
# factory側
class AbstractFactory:
 @classmethod
 def create_product1(cls):
   return cls.Product1()
 @abstractmethod
 def create_product2(self):
   return cls.Product2()

class FactoryA(AbstractFactory):
 class Product1:
     pass
 class Product2:
     pass

# client側
def main():
 product_1  = AbstractFactory.create_product1(FactoryA)
 product_2  = AbstractFactory.create_product2(Factory) 

メリットと使い所

  • メリット
    • インスタンス生成のロジックが、clientコードに依存しない(インターフェースに依存する)。
    • 作り方、作るもの、実際に作る、を別のモジュールに実装できる
  • 使い所
    • 生成方法がほぼ共通の場合に効果がある
    • 1つのFactoryクラスにて生成するProductの種類が増えることへの変化には弱い

 わかってないこと

1つのFactoryクラスにて生成するProductの種類が増えることへの変化には弱い

どのように対応(リファクタリング)するのか?

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4