forked from sloria/designpatterns.py
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfactory.py
More file actions
154 lines (120 loc) · 4.54 KB
/
factory.py
File metadata and controls
154 lines (120 loc) · 4.54 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
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
"""Factory pattern (abstract factory and factory method).
- Factory method - defines interface for creating *one* object; subclasses decide
which class to instantiate. Decouples client code from the
concrete product classes.
- Abstract factory - provides interface for creating *related* objects.
- Depend upon abstractions, not concrete classes
"""
from abc import ABCMeta, abstractmethod
# An abstract factory
# May not always be necessary. In Python, generally don't need to
# create superclasses just to share type
class PizzaIngredientFactory(metaclass=ABCMeta):
@abstractmethod
def create_dough(self): return
@abstractmethod
def create_sauce(self): return
@abstractmethod
def create_cheese(self): return
@abstractmethod
def create_pepperoni(self): return
# Concrete ingredient factory
class NYPizzaIngredientFactory(PizzaIngredientFactory):
def create_dough(self):
return "ThinCrustDough" # This would actually be an instantiated Dough object
# intead of just a string
def create_sauce(self):
return "MarinaraSauce"
def create_cheese(self):
return "ReggianoCheese"
def create_pepperoni(self):
return "SlicedPepperoni"
class ChicagoPizzaIngredientFactory(PizzaIngredientFactory):
def create_dough(self):
return "ThickCrustDough"
def create_sauce(self):
return "PlumTomatoSauce"
def create_cheese(self):
return "MozzarellaCheese"
def create_pepperoni(self):
return "SlicedPepperoni"
# Abstract product class
class Pizza(metaclass=ABCMeta):
name = ''
dough = ''
sauce =''
toppings = []
def __init__(self, ingredient_factory):
# Composing a factory decouples the Pizza class
# from regional ingredient differences
self.ingredient_factory = ingredient_factory
@abstractmethod
def prepare(self):
"""Collect ingredients from an ingredient factory and prepare the pizza.
"""
return
def bake(self):
print("Bake for 25 minutes at 350")
def cut(self):
print('Cutting the pizza into diagonal slices')
def box(self):
print("Place pizza in official PizzaStore box")
# Concrete Pizza classes
class CheesePizza(Pizza):
def prepare(self):
self.dough = self.ingredient_factory.create_dough()
self.sauce = self.ingredient_factory.create_sauce()
self.cheese = self.ingredient_factory.create_cheese()
class PepperoniPizza(Pizza):
def prepare(self):
self.dough = self.ingredient_factory.create_dough()
self.sauce = self.ingredient_factory.create_sauce()
self.cheese = self.ingredient_factory.create_cheese()
self.toppings.append(self.ingredient_factory.create_pepperoni())
class PizzaStore:
def order_pizza(self, item):
pizza = self.create_pizza(item)
pizza.prepare()
pizza.bake()
pizza.cut()
pizza.box()
return pizza
# Modified from original HFDP example. This method is shared by subclasses,
# so concrete classes only need to specify ingredient factory
def create_pizza(self, item):
if item == 'cheese':
pizza = CheesePizza(self.ingredient_factory)
pizza.name = "New York Style Cheese Pizza"
elif item == 'pepperoni':
pizza = PepperoniPizza(self.ingredient_factory)
pizza.name = "New York Style Pepperoni Pizza"
else:
return None
return pizza
# Concrete PizzaStore classes
class NYPizzaStore(PizzaStore):
ingredient_factory = NYPizzaIngredientFactory()
class ChicagoPizzaStore(PizzaStore):
ingredient_factory = ChicagoPizzaIngredientFactory()
def test_pizza_creation_with_ingredient_factory():
ing_factory = NYPizzaIngredientFactory()
pizza = CheesePizza(ing_factory)
pizza.prepare()
assert pizza.sauce == "MarinaraSauce"
assert pizza.dough == 'ThinCrustDough'
ing_factory2 = ChicagoPizzaIngredientFactory()
pizza2 = CheesePizza(ing_factory2)
pizza2.prepare()
assert pizza2.sauce == 'PlumTomatoSauce'
assert pizza2.dough == 'ThickCrustDough'
def test_create_pizza():
store = ChicagoPizzaStore()
pizza = store.create_pizza('pepperoni')
pizza.prepare()
assert pizza.sauce == 'PlumTomatoSauce'
assert 'SlicedPepperoni' in pizza.toppings
def test_order_pizza():
store = ChicagoPizzaStore()
pizza = store.order_pizza('pepperoni')
assert pizza.sauce == 'PlumTomatoSauce'
assert 'SlicedPepperoni' in pizza.toppings