---
title: "CP3 - Builder - Design Pattern From Simple Things"
description: "Building a house involves bringing together many parts, each house has its own specific requirements, you need a builder who can easily implement what you want."
pubDate: "2022-11-22"
lang: "en"
slug: "cp3-builder-design-pattern-from-simple-things"
url: "https://hoangyell.com/cp3-builder-design-pattern-from-simple-things/"
author: "HoangYell"
categories: ["Software Craft"]
tags: ["design-patterns", "creational-patterns"]
heroImage: "https://raw.githubusercontent.com/HoangGeek/store/main/webp/N3SbEFC.webp"
---

_Builder is a **creational** design pattern:_
🖤🤍🤍🤍🤍
> Design patterns can often be replaced by built-in language features so some `pattern/language` don't need to be implemented anymore. `Builder/Python` is a good example of that evil!

## What is  Builder?

Builder is the guy helping you to create object based on your requirements, tell the builder what you want, then he will give the expected outcome

![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/203665788-3354dbea-2b04-4586-accf-b7647167fc09.webp)

## Why use Builder?
I don't know about other languages, but in Python you don't need it, It looks stupid when you use Builder with Python.

**Question:** _Why Builder is stupid in Python?_

**Answer:** _Since Python supports [Named Parameters](https://en.wikipedia.org/wiki/Named_parameter)_ 🤖 _, the built-in feature is nicer than Builder_ 👷‍♂️

![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/sXyG3GX.webp)

## When to use Builder?

**Question:** _If I still want to use `Builder`, when can I use it?_

**Answer:** _When you need to create multiple variations of a class_

### Input:
  - Knowing how to build house parts:
    - `Ground Floor`
    - `First Floor`
    - `Roof`
```python
# nothing here
```
### Expected Output:
 - Getting 3 houses:
    - House without `Roof`
    - Simple House (House without `First Floor`)
    - Advanced House (House has all parts: `Ground Floor, First Floor, Roof`)
```shell
O
U
--
^
U
--
^
O
U
```

## How to implement Builder?

### Non-Builder implementation:
```python
class NormalHouse:
    def __init__(self, has_ground_floor=False, has_first_floor=False, has_roof=False):
        self.parts = []
        if has_ground_floor:
            ground = "U"
            self.parts.append(ground)
        if has_first_floor:
            first_floor = "O"
            self.parts.append(first_floor)
        if has_roof:
            roof = "^"
            self.parts.append(roof)

    def show_off(self):
        print("\n".join(self.parts[::-1]))

if __name__ == "__main__":
    normal_house = NormalHouse(has_ground_floor=True, has_first_floor=True)
    normal_house.show_off()
    print("--")
    simple_house = NormalHouse(has_ground_floor=True, has_roof=True)
    simple_house.show_off()
    print("--")
    normal_house = NormalHouse(
        has_ground_floor=True, has_first_floor=True, has_roof=True
    )
    normal_house.show_off()
```

### Builder implementation:
```python
from abc import abstractmethod

class Builder:
    @property
    @abstractmethod
    def house(self):
        pass

    @abstractmethod
    def build_roof(self):
        pass

    @abstractmethod
    def build_ground_floor(self):
        pass

    @abstractmethod
    def build_first_floor(self):
        pass

class NormalHouseBuilder(Builder):
    def __init__(self):
        self.reset()

    def reset(self):
        self._house = NormalHouse()

    @property
    def house(self):
        house = self._house
        self.reset()
        return house

    def build_roof(self):
        roof = "^"
        self._house.add(roof)

    def build_ground_floor(self):
        ground = "U"
        self._house.add(ground)

    def build_first_floor(self):
        first_floor = "O"
        self._house.add(first_floor)

class NormalHouse:
    def __init__(self):
        self.parts = []

    def add(self, part):
        self.parts.append(part)

    def show_off(self):
        print("\n".join(self.parts[::-1]))

class Director:
    def __init__(self, builder):
        self.builder = builder

    def build_simple_house(self):
        self.builder.build_ground_floor()
        self.builder.build_roof()

    def build_advanced_house(self):
        self.builder.build_ground_floor()
        self.builder.build_first_floor()
        self.builder.build_roof()

if __name__ == "__main__":
    builder = NormalHouseBuilder()
    builder.build_ground_floor()
    builder.build_first_floor()
    builder.house.show_off()
    print("--")
    director = Director(builder)
    director.build_simple_house()
    builder.house.show_off()
    print("--")
    director.build_advanced_house()
    builder.house.show_off()
```

[Source Code](https://github.com/HoangYell/Design-Pattern-From-Simple-Things/blob/main/cp3_builder.py)
