趣旨
駆け出しエンジニアの備忘録の垂れ流し。
※ 出典漏れがあればご指摘ください
出典:
https://yamakatsusan.web.fc2.com/
https://dackdive.hateblo.jp/
https://www.oreilly.co.jp/books/9784873117393/
prottypeパターン概要
生成に関するデザインパターンの1つ。
「生成すべきオブジェクトの種類を原型となるインスタンスを作り、それを複製することで目的のオブジェクトの生成を行う」
インスタンスの生成にコスト(時間的や資源的)がかかる場合や、クラスとして規定するまでもないが(もしくはすべての種別をクラスとして実装するのが現実的ではないが)複数のインスタンスに個別の属性値を付与したい、異なる振る舞いのメソッドを実装する場合などに利用する。
利用頻度はそんなに高くなさそう
クラス図とシーケンス図
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)
使い所
- 使い所
- インスタンスの生成にコスト(時間的や資源的)がかかる、かつ、複数のインスタンスを生成するケース
- クラスとして規定するするまでもないが(もしくはすべての種別をクラスとして実装するのが現実的ではないが)複数のインスタンスに個別の属性値を付与したい、異なる振る舞いのメソッドを実装したいケース