-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathabstract_factory.py
169 lines (108 loc) · 3.72 KB
/
abstract_factory.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
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
from abc import ABC, abstractmethod
# We start by creating some abstract ingredients.
# These will be extended by each region-specific ingredients
class Dough:
pass
class Sauce:
pass
class Cheese:
pass
class Pepperoni:
pass
# Normally, in OO languages such as Java, the abstract factory
# is implemented through interfaces. However because we don't
# have those in Python, we will use abstract classes instead.
class PizzaIngredientFactory(ABC):
@abstractmethod
def createDough() -> Dough:
pass
@abstractmethod
def createSauce() -> Sauce:
pass
@abstractmethod
def createCheese() -> Cheese:
pass
@abstractmethod
def createPepperoni() -> Pepperoni:
pass
# Before creating the concrete region-specific PizzaIgredientFactories
# we need to create some concrete ingredients by extending the abstract
# ingredient classes
class ThinCrustDough(Dough):
pass
class MarinaraSauce(Sauce):
pass
class ReggianoCheese(Cheese):
pass
class SlicedPepperoni(Pepperoni):
pass
# We now have everything we need to create the concrete New York
# PizzaIngredientFactory:
class NYPizzaIngredientFactory(PizzaIngredientFactory):
def createDough(self):
return ThinCrustDough()
def createSauce(self):
return MarinaraSauce()
def createCheese(self):
return ReggianoCheese()
def createPepperoni(self):
return SlicedPepperoni()
# The next step is to modify our abstract Pizza class so that
# it uses our newly created ingredients
class Pizza(ABC):
# We add here the dependency ingredients
dough: Dough
sauce: Sauce
cheese: Cheese
pepperoni: Pepperoni
@abstractmethod
def prepare(self):
pass
def bake(self):
print("baking pizza for 12min in 400 degrees..")
def cut(self):
print("cutting pizza in pieces")
def box(self):
print("putting pizza in box")
# Now we can create some concrete Pizzas. Note that all pizzas
# will have an PizzaIngredientFactory dependency that will be
# responsible for creating all the proper ingredients:
class CheesePizza(Pizza):
ingredientFactory: PizzaIngredientFactory
def __init__(self, ingredientFactory: PizzaIngredientFactory):
self.ingredientFactory = ingredientFactory
# We also need to override the prepare() abstract method:
def prepare(self):
# Since this is a CheesePizza we don't put any pepperoni:
self.dough = self.ingredientFactory.createDough()
self.sauce = self.ingredientFactory.createSauce()
self.cheese = self.ingredientFactory.createCheese()
# The PizzaStore remains unchanged (same as in the Factory Method pattern)
class PizzaStore(ABC):
@abstractmethod
def _createPizza(self, pizzaType: str) -> Pizza:
pass
def orderPizza(self, pizzaType):
pizza: Pizza
pizza = self._createPizza(pizzaType)
pizza.prepare()
pizza.bake()
pizza.cut()
pizza.box()
# Remember that PizzaStore calls the prepare(), bake(), etc in the orderPizza
# so here we only need to override the _createPizza method:
class NYPizzaStore(PizzaStore):
def _createPizza(self, pizzaType: str) -> Pizza:
pizza: Pizza = None
ingredientFactory: PizzaIngredientFactory = NYPizzaIngredientFactory()
if pizzaType == "Greek":
# Prepare the greek pizza here after creating
# the proper ingredients and then the GreekPizza
pass
elif pizzaType == "Cheese":
pizza = CheesePizza(ingredientFactory)
else:
print("No matching pizza found in the NY pizza store...")
return pizza
store = NYPizzaStore()
store.orderPizza("Cheese")