Builder Design Pattern
Video Lecture
Overview
The Builder Pattern is a creational pattern whose intent is to separate the construction of a complex object from its representation so that you can use the same construction process to create different representations.
The Builder Pattern tries to solve,
- How can a class create different representations of a complex object?
- How can a class that includes creating a complex object be simplified?
The Builder and Factory patterns are very similar in the fact they both instantiate new objects at runtime. The difference is when the process of creating the object is more complex, so rather than the Factory returning a new instance of ObjectA
, it calls the builders director constructor method ObjectA.construct()
that goes through a more complex construction process involving several steps. Both return an Object/Product.
Terminology
- Product: The Product being built.
- Builder: Builds the concrete product. Implements the
IBuilder
interface.
- Builder Interface: The Interface that the Concrete builder should implement.
- Director: Has a
construct()
method that when called creates a customized product.
Builder UML Diagram

Source Code
... Refer to Book, pause Video Lectures or subscribe to Medium Membership to read textual content.
./builder/builder_concept.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 | # pylint: disable=too-few-public-methods
"Builder Concept Sample Code"
from abc import ABCMeta, abstractmethod
class IBuilder(metaclass=ABCMeta):
"The Builder Interface"
@staticmethod
@abstractmethod
def build_part_a():
"Build part a"
@staticmethod
@abstractmethod
def build_part_b():
"Build part b"
@staticmethod
@abstractmethod
def build_part_c():
"Build part c"
@staticmethod
@abstractmethod
def get_result():
"Return the final product"
class Builder(IBuilder):
"The Concrete Builder."
def __init__(self):
self.product = Product()
def build_part_a(self):
self.product.parts.append('a')
return self
def build_part_b(self):
self.product.parts.append('b')
return self
def build_part_c(self):
self.product.parts.append('c')
return self
def get_result(self):
return self.product
class Product():
"The Product"
def __init__(self):
self.parts = []
class Director:
"The Director, building a complex representation."
@staticmethod
def construct():
"Constructs and returns the final product"
return Builder()\
.build_part_a()\
.build_part_b()\
.build_part_c()\
.get_result()
# The Client
PRODUCT = Director.construct()
print(PRODUCT.parts)
|
Output
| python ./builder/builder_concept.py
['a', 'b', 'c']
|
Example Use Case
... Refer to Book, pause Video Lectures or subscribe to Medium Membership to read textual content.
Example UML Diagram

Source Code
./builder/client.py
1
2
3
4
5
6
7
8
9
10
11
12
13 | "House Builder Example Code"
from igloo_director import IglooDirector
from castle_director import CastleDirector
from houseboat_director import HouseBoatDirector
IGLOO = IglooDirector.construct()
CASTLE = CastleDirector.construct()
HOUSEBOAT = HouseBoatDirector.construct()
print(IGLOO.construction())
print(CASTLE.construction())
print(HOUSEBOAT.construction())
|
./builder/igloo_director.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | "A Director Class"
from house_builder import HouseBuilder
class IglooDirector: # pylint: disable=too-few-public-methods
"One of the Directors, that can build a complex representation."
@staticmethod
def construct():
"""Constructs and returns the final product
Note that in this IglooDirector, it has omitted the set_number_of
windows call since this Igloo will have no windows.
"""
return HouseBuilder()\
.set_building_type("Igloo")\
.set_wall_material("Ice")\
.set_number_doors(1)\
.get_result()
|
./builder/castle_director.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | "A Director Class"
from house_builder import HouseBuilder
class CastleDirector: # pylint: disable=too-few-public-methods
"One of the Directors, that can build a complex representation."
@staticmethod
def construct():
"Constructs and returns the final product"
return HouseBuilder()\
.set_building_type("Castle")\
.set_wall_material("Sandstone")\
.set_number_doors(100)\
.set_number_windows(200)\
.get_result()
|
./builder/houseboat_director.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | "A Director Class"
from house_builder import HouseBuilder
class HouseBoatDirector: # pylint: disable=too-few-public-methods
"One of the Directors, that can build a complex representation."
@staticmethod
def construct():
"Constructs and returns the final product"
return HouseBuilder()\
.set_building_type("House Boat")\
.set_wall_material("Wood")\
.set_number_doors(6)\
.set_number_windows(8)\
.get_result()
|
./builder/interface_house_builder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | "The Builder Interface"
from abc import ABCMeta, abstractmethod
class IHouseBuilder(metaclass=ABCMeta):
"The House Builder Interface"
@staticmethod
@abstractmethod
def set_building_type(building_type):
"Build type"
@staticmethod
@abstractmethod
def set_wall_material(wall_material):
"Build material"
@staticmethod
@abstractmethod
def set_number_doors(number):
"Number of doors"
@staticmethod
@abstractmethod
def set_number_windows(number):
"Number of windows"
@staticmethod
@abstractmethod
def get_result():
"Return the final product"
|
./builder/house_builder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | "The Builder Class"
from interface_house_builder import IHouseBuilder
from house import House
class HouseBuilder(IHouseBuilder):
"The House Builder."
def __init__(self):
self.house = House()
def set_building_type(self, building_type):
self.house.building_type = building_type
return self
def set_wall_material(self, wall_material):
self.house.wall_material = wall_material
return self
def set_number_doors(self, number):
self.house.doors = number
return self
def set_number_windows(self, number):
self.house.windows = number
return self
def get_result(self):
return self.house
|
./builder/house.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | "The Product"
class House(): # pylint: disable=too-few-public-methods
"The Product"
def __init__(self, building_type="Apartment", doors=0,
windows=0, wall_material="Brick"):
# brick, wood, straw, ice
self.wall_material = wall_material
# Apartment, Bungalow, Caravan, Hut, Castle, Duplex,
# HouseBoat, Igloo
self.building_type = building_type
self.doors = doors
self.windows = windows
def construction(self):
"Returns a string describing the construction"
return f"This is a {self.wall_material} "\
f"{self.building_type} with {self.doors} "\
f"door(s) and {self.windows} window(s)."
|
Output
| python ./builder/client.py
This is a Ice Igloo with 1 door(s) and 0 window(s).
This is a Sandstone Castle with 100 door(s) and 200 window(s).
This is a Wood House Boat with 6 door(s) and 8 window(s).
|
New Coding Concepts
Python List
In the file ./builder/builder_concept.py
| def __init__(self):
self.parts = []
|
The []
is indicating a Python List.
The list can store multiple items, they can be changed, they can have items added and removed, can be re-ordered, can be pre-filled with items when instantiated and is also very flexible.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | PS> python
>>> items = []
>>> items.append("shouldn't've")
>>> items.append("y'aint")
>>> items.extend(["whomst", "superfluity"])
>>> items
["shouldn't've", "y'aint", 'whomst', 'superfluity']
>>> items.reverse()
>>> items
['superfluity', 'whomst', "y'aint", "shouldn't've"]
>>> items.remove("y'aint")
>>> items
['superfluity', 'whomst', "shouldn't've"]
>>> items.insert(1, "phoque")
>>> items
['superfluity', 'phoque', 'whomst', "shouldn't've"]
>>> items.append("whomst")
>>> items.count("whomst")
2
>>> len(items)
5
>>> items[2] = "bagnose"
>>> items
['superfluity', 'phoque', 'bagnose', "shouldn't've", 'whomst']
>>> items[-2]
"shouldn't've"
|
Lists are used in almost every code example in this documentation. You will see all the many ways they can be used.
In fact, a list was used in the Abstract Factory example,
| if furniture in ['SmallChair', 'MediumChair', 'BigChair']:
...
|
This line, creates a list at runtime including the strings 'SmallChair', 'MediumChair' and 'BigChair'. If the value in furniture
equals the same string as one of those items in the list, then the condition is true and the code within the if statement block will execute.
Summary
... Refer to Book, pause Video Lectures or subscribe to Medium Membership to read textual content.