Builderパターン(4) Builderの再利用

Rubyによるデザインパターン』(ラス・オルセン著 ピアソン・エデュケーション刊)の例をPythonに変換して書いています。目次


Builderを1回作ったら、そのBuilderを何回も使って、オブジェクトを量産する事ができます。

しかし、以前作ったComputerBuilderでは、コンピュータを量産できません。

class ComputerBuilder(object):
    def __init__(self):
        self._computer = Computer()
   
    (中略)
 
    def computer(self):
        return self._computer

最初に1個、Computerを作り、それを直接変更しているからです。従って、ComputerBuilder.computer() を何度呼んでも、同一インスタンスが返されてきます。

これを避けるには、ディスプレイの種類・メモリサイズ・ドライブ等の情報を、Builder自身が保持し、

本当のComputerを作るのは、ComputerBuilder.__init__ではなく、ComputerBuilder.computerの中、という風にする必要があります。

class ComputerBuilder(object):
    def __init__(self):
        self._display = "crt"
        self._has_turbo_cpu = False
        self._memory_size=1024
        self._drives_args = []
    
    def set_turbo(self, has_turbo_cpu=True):
        self._has_turbo_cpu = has_turbo_cpu
        
    def set_display(self, display):
        self._display = display
    
    def set_memory_size(self, size_in_mb):
        self._memory_size = size_in_mb
    
    def add_cd(self, writable=False):
        self._drives_args.append(("cd", 760, writable))

    def add_dvd(self, writable=False):
        self._drives_args.append(("dvd", 4000, writable))

    def add_harddisk(self, size_in_mb):
        self._drives_args.append(("harddisk", size_in_mb, True))
    
    def computer(self):
        if self._has_turbo_cpu:
            cpu = TurboCPU()
        else:
            cpu = BasicCPU()
        motherboard = Motherboard(cpu, self._memory_size)
        
        drives = []
        for type, size, writable in self._drives_args:
            drives.append(Drive(type, size, writable))
        
        return Computer(self._display, motherboard, drives)