LoginSignup
1
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-05-07

趣旨

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

出典:
https://yamakatsusan.web.fc2.com/
https://dackdive.hateblo.jp/
https://www.oreilly.co.jp/books/9784873117393/

prottypeパターン概要

生成に関するデザインパターンの1つ。
「生成すべきオブジェクトの種類を原型となるインスタンスを作り、それを複製することで目的のオブジェクトの生成を行う」
インスタンスの生成にコスト(時間的や資源的)がかかる場合や、クラスとして規定するまでもないが(もしくはすべての種別をクラスとして実装するのが現実的ではないが)複数のインスタンスに個別の属性値を付与したい、異なる振る舞いのメソッドを実装する場合などに利用する。
利用頻度はそんなに高くなさそう

クラス図とシーケンス図

640px-Prototype_UML.svg.png

W3sDesign_Prototype_Design_Pattern_UML.jpg

wikipediaより引用

実装方針

  • Prototypeクラスはインスタンスを複製するための基底メソッド(clone)を規定する(template methodパターン)。※インスタンスを利用するための規定メソッド(use)も必要であれば規定する。
  • Prototypeサブクラス(ConcretePrototypeクラス)にインスタンスを実際に複製する責務を持たせる。cloneメソッドをオーバーライド。 selfをdeepcopyしたオブジェクトを返すメソッドとする。
  • オブジェクトの生成を管理するManagerクラスがあると便利。Managerクラスは、複製元のインスタンスを保持させ、指定に応じたインスタンスを複製するメソッドを実装する。
  • Client側ではManagerのIFを呼び出す処理を実装する。
実装例1
# prototype側
class Prototype:
  @abstractmethod
  def use(self):
    pass
  @abstractmethod
  def create(self)
    pass

class ConcretePrototype1(Prototype):
  def use(self):
    do_something1()

  def create(self)
    clone = copy.deepcopy(self) # deep copyとshallow copyに注意
    clone.set_parameter1(some_args)
    return clone

class ConcretePrototype2(Prototype):
  def use(self):
    do_something2()

  def create(self, some_args)
    clone = copy.deepcopy(self)
    clone.set_parameter2(some_args)
    return clone

# Manager側(例)
class CreatingPrototypeManager:
   def __init__(self):
        self.__ins_dict = {}
   def register_ins(self, prot_ins_key: str, prot_ins: Prototype):
       self.__ins_dict[prot_ins_key]
   def create_ins(self, prot_ins_keye, some_args: obj) 
       ins = self.__ins_dict[prot_ins_key]
       ins.set_params(some_args)
       return ins
# client側
def main():
 prot1 = ConcretePrototype1()
 prot2 = ConcretePrototype2()
 prot_mgr = CreatingPrototypeManager()
 prot_mgr.register_ins("prot1", prot1)
 prot_mgr.register_ins("prot2", prot2)
 # register_insまでの処理はManagerに持たせても良い) 

 ins1 = prot_mgr.create_ins("prot1", params1)
 ins1 = prot_mgr.create_ins("prot1", params2)
 ins1 = prot_mgr.create_ins("prot1", params3)
 ins2 = prot_mgr.create_ins("prot1", params4)

使い所

  • 使い所
    • インスタンスの生成にコスト(時間的や資源的)がかかる、かつ、複数のインスタンスを生成するケース 
    • クラスとして規定するするまでもないが(もしくはすべての種別をクラスとして実装するのが現実的ではないが)複数のインスタンスに個別の属性値を付与したい、異なる振る舞いのメソッドを実装したいケース
1
2
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
2