forked from faif/python-patterns
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuilder.py
More file actions
Latest commit
111 lines (79 loc) · 2.92 KB
/
Copy pathbuilder.py
File metadata and controls
111 lines (79 loc) · 2.92 KB
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/python
# -*- coding : utf-8 -*-
"""
*What is this pattern about?
It decouples the creation of a complex object and its representation,
so that the same process can be reused to build objects from the same
family.
This is useful when you must separate the specification of an object
from its actual representation (generally for abstraction).
*What does this example do?
The first example achieves this by using an abstract base
class for a building, where the initializer (__init__ method) specifies the
steps needed, and the concrete subclasses implement these steps.
In other programming languages, a more complex arrangement is sometimes
necessary. In particular, you cannot have polymorphic behaviour in a constructor in C++ -
see https://stackoverflow.com/questions/1453131/how-can-i-get-polymorphic-behavior-in-a-c-constructor
- which means this Python technique will not work. The polymorphism
required has to be provided by an external, already constructed
instance of a different class.
In general, in Python this won't be necessary, but a second example showing
this kind of arrangement is also included.
*Where is the pattern used practically?
*References:
https://sourcemaking.com/design_patterns/builder
*TL;DR
Decouples the creation of a complex object and its representation.
"""
# Abstract Building
classBuilding(object):
def__init__(self):
self.build_floor()
self.build_size()
defbuild_floor(self):
raiseNotImplementedError
defbuild_size(self):
raiseNotImplementedError
def__repr__(self):
return'Floor: {0.floor} | Size: {0.size}'.format(self)
# Concrete Buildings
classHouse(Building):
defbuild_floor(self):
self.floor='One'
defbuild_size(self):
self.size='Big'
classFlat(Building):
defbuild_floor(self):
self.floor='More than One'
defbuild_size(self):
self.size='Small'
# In some very complex cases, it might be desirable to pull out the building
# logic into another function (or a method on another class), rather than being
# in the base class '__init__'. (This leaves you in the strange situation where
# a concrete class does not have a useful constructor)
classComplexBuilding(object):
def__repr__(self):
return'Floor: {0.floor} | Size: {0.size}'.format(self)
classComplexHouse(ComplexBuilding):
defbuild_floor(self):
self.floor='One'
defbuild_size(self):
self.size='Big and fancy'
defconstruct_building(cls):
building=cls()
building.build_floor()
building.build_size()
returnbuilding
# Client
if__name__=="__main__":
house=House()
print(house)
flat=Flat()
print(flat)
# Using an external constructor function:
complex_house=construct_building(ComplexHouse)
print(complex_house)
### OUTPUT ###
# Floor: One | Size: Big
# Floor: More than One | Size: Small
# Floor: One | Size: Big and fancy