Skip to content

Commit ee330db

Browse files
committed
Further simplifications to builder pattern
1 parent 1671517 commit ee330db

File tree

1 file changed

+55
-36
lines changed

1 file changed

+55
-36
lines changed

‎creational/builder.py‎

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@
1010
from its actual representation (generally for abstraction).
1111
1212
*What does this example do?
13-
This particular example uses a director function to abstract the
14-
construction of a building. The user specifies a Builder (House or
15-
Flat) and the director specifies the methods in the order necessary,
16-
creating a different building depending on the specification
17-
(from the Builder class).
1813
19-
@author: Diogenes Augusto Fernandes Herminio <[email protected]>
20-
https://gist.github.com/420905#file_builder_python.py
14+
The first example achieves this by using an abstract base
15+
class for a building, where the initializer (__init__ method) specifies the
16+
steps needed, and the concrete subclasses implement these steps.
17+
18+
In other programming languages, a more complex arrangement is sometimes
19+
necessary. In particular, you cannot have polymorphic behaviour in a
20+
constructor in C++ - see https://stackoverflow.com/questions/1453131/how-can-i-get-polymorphic-behavior-in-a-c-constructor
21+
- which means this Python technique will not work. The polymorphism
22+
required has to be provided by an external, already constructed
23+
instance of a different class.
24+
25+
In general, in Python this won't be necessary, but a second example showing
26+
this kind of arrangement is also included.
2127
2228
*Where is the pattern used practically?
2329
@@ -29,67 +35,80 @@
2935
"""
3036

3137

32-
defconstruct_building(builder):
33-
builder.new_building()
34-
builder.build_floor()
35-
builder.build_size()
36-
returnbuilder.building
37-
38-
39-
# Abstract Builder
40-
classBuilder(object):
38+
# Abstract Building
39+
classBuilding(object):
4140

4241
def__init__(self):
43-
self.building=None
44-
45-
defnew_building(self):
46-
self.building=Building()
42+
self.build_floor()
43+
self.build_size()
4744

4845
defbuild_floor(self):
4946
raiseNotImplementedError
5047

5148
defbuild_size(self):
5249
raiseNotImplementedError
5350

54-
# Concrete Builder
51+
def__repr__(self):
52+
return'Floor:{0.floor} | Size:{0.size}'.format(self)
5553

5654

57-
classBuilderHouse(Builder):
55+
# Concrete Buildings
56+
classHouse(Building):
5857

5958
defbuild_floor(self):
60-
self.building.floor='One'
59+
self.floor='One'
6160

6261
defbuild_size(self):
63-
self.building.size='Big'
62+
self.size='Big'
6463

6564

66-
classBuilderFlat(Builder):
65+
classFlat(Building):
6766

6867
defbuild_floor(self):
69-
self.building.floor='More than One'
68+
self.floor='More than One'
7069

7170
defbuild_size(self):
72-
self.building.size='Small'
71+
self.size='Small'
7372

7473

75-
# Product
76-
classBuilding(object):
74+
# In some very complex cases, it might be desirable to pull out the building
75+
# logic into another function (or a method on another class), rather than being
76+
# in the base class '__init__'. (This leaves you in the strange situation where
77+
# a concrete class does not have a useful constructor)
7778

78-
def__init__(self):
79-
self.floor=None
80-
self.size=None
8179

80+
classComplexBuilding(object):
8281
def__repr__(self):
8382
return'Floor:{0.floor} | Size:{0.size}'.format(self)
8483

8584

85+
classComplexHouse(ComplexBuilding):
86+
defbuild_floor(self):
87+
self.floor='One'
88+
89+
defbuild_size(self):
90+
self.size='Big and fancy'
91+
92+
93+
defconstruct_building(cls):
94+
building=cls()
95+
building.build_floor()
96+
building.build_size()
97+
returnbuilding
98+
99+
86100
# Client
87101
if__name__=="__main__":
88-
building=construct_building(BuilderHouse())
89-
print(building)
90-
building=construct_building(BuilderFlat())
91-
print(building)
102+
house=House()
103+
print(house)
104+
flat=Flat()
105+
print(flat)
106+
107+
# Using an external constructor function:
108+
complex_house=construct_building(ComplexHouse)
109+
print(complex_house)
92110

93111
### OUTPUT ###
94112
# Floor: One | Size: Big
95113
# Floor: More than One | Size: Small
114+
# Floor: One | Size: Big and fancy

0 commit comments

Comments
(0)