『Rubyによるデザインパターン』(ラス・オルセン著 ピアソン・エデュケーション刊)の例をPythonに変換して書いています。目次
- Builderパターン(1)
- Builderパターン(2) ポリモーフィックなBuilder
- Builderパターン(3) Builderでオブジェクトの妥当性を保証する
- Builderパターン(4) Builderの再利用
コンストラクタの引数がやたら多いなど、初期化が面倒なオブジェクトがあったとき、初期化をやりやすくするのが、Builderパターンです。
コンピュータ製造プログラムを作っているとします。
コンピュータには、ディスプレイの種類・マザーボード・DVDやHDのドライブなどによって、パラメータ化されています。さらに、マザーボードも複数の部品から出来ています。
class Computer(object): def __init__(self, display="crt", motherboard=Motherboard(), drives=[]): self.display = display self.motherboard = motherboard self.drives = drives class CPU(object): #CPU共通のコード class BasicCPU(object): #安いCPUについてのたくさんのコード class TurboCPU(object): #超高速CPUについてのたくさんのコード class Motherboard(object): def __init__(self, cpu=BasicCPU(), memory_size=1024): self.cpu = cpu self.memory_size = memory_size class Drive(object): def __init__(self, type, size, writable): """ type: "harddistk" か "cd" か "dvd" size: MBで writable: 書き込み可能かどうか """ self.type = type self.size = size self.writable = writable
#組み立ての実際 motherboard = Motherboard(TurboCPU(), 4000) drives = [] drives.append(Drive("harddisk", 1024*1024*1024, True)) drives.append(Drive("dvd", 1024*4.7, True)) drives.append(Drive("dvd", 1024*8.5, False)) computer = Computer("lcd", motherboard, drives)
非常に単純なモデルにも関わらず、組み立てはかなり退屈な作業です。
この種の組み立てのロジックをカプセル化したのが、Builderです。
class ComputerBuilder(object): def __init__(self): self._computer = Computer() def set_turbo(self, has_turbo_cpu=True): if has_turbo_cpu: self._computer.motherboard.cpu = TurboCPU else: self._computer.motherboard.cpu = BasicCPU def set_display(self, display): self._computer.display = display def set_memory_size(self, size_in_mb): self._computer.motherboard.memory_size = size_in_mb def add_cd(self, writable=False): self._computer.drives.append(Drive("cd", 760, writable)) def add_dvd(self, writable=False): self._computer.drives.append(Drive("dvd", 4000, writable)) def add_harddisk(self, size_in_mb): self._computer.drives.append(Drive("harddisk", size_in_mb, True)) def computer(self): return self._computer #つかいかた builder = ComputerBuilder() builder.set_turbo() builder.add_cd(True) builder.add_dvd() builder.add_harddisk(1024*1024*1024) computer = builder.computer()
Builderはいわば、複数に分けられた__init__ です。一息に作る代わりに、何段階かに分けてオブジェクトを作るのです。