PythonでPrototypeパターン
Prototypeパターンではあるオブジェクトをコピーすることで新しいオブジェクトを作成する.
実装するには,属性値をコピーして新しいオブジェクトを返すメソッドを定義する.
#!/usr/bin/python class Prototype(object): def __init__(self, prototype = None): if prototype: self.value = prototype.getValue(); else: self.value = 0; def increment(self): self.value += 1; def getValue(self): return self.value; def clone(self): return Prototype(self); class PrototypeA(Prototype): def __init__(self, prototype = None): Prototype.__init__(self, prototype); self.value = 0.0; if __name__ == '__main__': a = Prototype(); print "a.getValue() = " + str(a.getValue()); a.increment(); print "a.getValue() = " + str(a.getValue()); b = a.clone(); print "b.getValue() = " + str(b.getValue()); c = PrototypeA(); c.increment(); print "c.getValue() = " + str(c.getValue()); d = c.clone(); print "d.getValue() = " + str(d.getValue()); c.increment(); print "c.getValue() = " + str(c.getValue()); print "d.getValue() = " + str(d.getValue());
実行結果.b, dはともにa, cをプロトタイプとして作成されたオブジェクト.当然それぞれ独立して属性値を変更できる.
a.getValue() = 0 a.getValue() = 1 b.getValue() = 1 ← aをコピーしてbが作られている.だから値も一緒 c.getValue() = 1.0 d.getValue() = 1.0 ← cをコピーしてbが作られている.だから値も一緒 c.getValue() = 2.0 ← c.increment()を呼び出す.よってc.getValue()は2.0を返す d.getValue() = 1.0 ← dとcは別のオブジェクトのため,c.increment()はdの状態に影響を与えない
今は単純なオブジェクトだったので考えなくても良かったが,属性値がオブジェクトだった場合,そのオブジェクトもコピーしなくてはならないと思われる.
作ってから調べたら,Pythonには浅い/深いコピーを実現するライブラリがあるようだ:3.18 copy -- 浅いコピーおよび深いコピー操作.これを使うともっと簡単に実現できる.
import copy; class Prototype(object): def __init__(self): self.value = 0; def increment(self): self.value += 1; def getValue(self): return self.value; def clone(self): return copy.deepcopy(self); class PrototypeA(Prototype): def __init__(self): self.value = 0.0;