Search code examples
pythonsoftware-designsolid-principles

Implementing the builder pattern in python


I have been studying design patterns. I am struggling with finding a scenario that I can implement builder pattern for that scenario. Has anyone got any example in python?


Solution

  • In this code, we are going to build a computer for our AppleFactory which would look like the below code without a design pattern (Builder pattern in this case).

    MINI14 = '1.4GHz Mac mini'
    
    
    class AppleFactory:
        class MacMini14:
            def __init__(self):
                self.memory = 4  # in gigabytes
                self.hdd = 500  # in gigabytes
                self.gpu = 'Intel HD Graphics 5000'
    
            def __str__(self):
                info = (f'Model: {MINI14}',
                        f'Memory: {self.memory}GB',
                        f'Hard Disk: {self.hdd}GB',
                        f'Graphics Card: {self.gpu}')
                return '\n'.join(info)
    
        def build_computer(self, model):
            if model == MINI14:
                return self.MacMini14()
            else:
                msg = f"I don't know how to build {model}"
                print(msg)
    
    
    if __name__ == '__main__':
        afac = AppleFactory()
        mac_mini = afac.build_computer(MINI14)
        print(mac_mini)
    

    Let's use the Builder design pattern to decouple the above code.

    class Computer:
        def __init__(self, serial_number):
            self.serial = serial_number
            self.memory = None # in gigabytes
            self.hdd = None # in gigabytes
            self.gpu = None
        def __str__(self):
            info = (f'Memory: {self.memory}GB',
                    f'Hard Disk: {self.hdd}GB',
                    f'Graphics Card: {self.gpu}')
            return '\n'.join(info)
    
    class ComputerBuilder:
        def __init__(self):
            self.computer = Computer('AG23385193')
        def configure_memory(self, amount):
            self.computer.memory = amount
        def configure_hdd(self, amount):
            self.computer.hdd = amount
        def configure_gpu(self, gpu_model):
            self.computer.gpu = gpu_model
    
    class HardwareEngineer:
        def __init__(self):
            self.builder = None
        def construct_computer(self, memory, hdd, gpu):
            self.builder = ComputerBuilder()
            steps = (self.builder.configure_memory(memory),
            self.builder.configure_hdd(hdd),
            self.builder.configure_gpu(gpu))
            [step for step in steps]
    
        @property
        def computer(self):
            return self.builder.computer
    
    def main():
        engineer = HardwareEngineer()
        engineer.construct_computer(hdd=500,memory=8,gpu='GeForce GTX 650 Ti')
        computer = engineer.computer
        print(computer)
        
    if __name__ == '__main__':
        main()
    

    Here, we have decoupled our code into 3 classes - Computer, ComputerBuilder, and HardwareEngineer such that anyone can just call HardwareEngineer class and build.