『Rubyによるデザインパターン』(ラス・オルセン著 ピアソン・エデュケーション刊)の例をPythonに変換して書いています。目次
- Factoryパターン(1) - Factory Method
- Factoryパターン(2) - 引数にクラスを渡すFactory Method
- Factoryパターン(3) - Abstract Factory
- Factoryパターン(4) - 引数にクラスを渡すAbstract Factory
Factory Methodでは、メソッドにクラスを引数として与える事が出来ます。
ところで、前回、池の生態系シミュレータを作りましたが、やはり池には藻や葦が生えてないとおかしいという事になり、「植物」に関する機能を追加する事にしました。
class Pond(object): def __init__(self, number_animals, number_plants): self.animals = [] for i in xrange(number_animals): animal = self.new_animal("動物%d"%(i,)) self.animals.append(animal) self.plants = [] for i in xrange(number_plants): plant = self.new_plant("植物%d"%(i,)) self.plants.append(plant) class DuckWaterLilyPond(Pond): #ここにメソッドを定義 class FrogAlgaePond(Pond): #ここにメソッドを定義
このPondには問題があります。新種の動物・植物を追加するために、それを扱うPondのサブクラスがドンドン増えていく事です。
ここでPython(Rubyも)の特長を利用します。それはクラスもオブジェクトであるという事です。つまり、クラスを変数に代入したり、引数に渡したり出来るのです。
class Pond(object): def __init__(self, number_animals, animal_class number_plants, plant_class): self.animal_class = animal_class self.plant_class = plant_class self.animals = [] for i in xrange(number_animals): animal = self.new_organism("animal", "動物%d"%(i,)) self.animals.append(animal) self.plants = [] for i in xrange(number_plants): plant = self.new_organism("plant", "植物%d"%(i,)) self.plants.append(plant) def new_organism(self, type, name): if type == "plant": return self.plant_class(name) elif type == "animal": return self.animal_class(name) else: assert False, "wrong organism type %r"%(type,) pond = Pond(10, Frog, 5, Algae) pond.simulate_one_day()