-
Notifications
You must be signed in to change notification settings - Fork 32
/
open_closed.py
119 lines (87 loc) · 2.69 KB
/
open_closed.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
"""
Open-closed principle
- Classes should be open for extension but closed for
modification
"""
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
class Size(Enum):
SMALL = 1
MEDIUM = 2
LARGE = 3
class Product:
def __init__(self, name, color, size):
self.size = size
self.color = color
self.name = name
class ProductFilter:
def filter_by_color(self, products, color):
for p in products:
if p.color == color:
yield p
def filter_by_size(self, products, size):
for p in products:
if p.size == size:
yield p
def filter_by_size_and_color(self, products, size, color):
for p in products:
if p.color == color and p.size == size:
yield p
# Enterprise Patterns: Specification
class Specification:
def is_satisfied(self, item):
pass
# syntatic sugar
def __and__(self, other):
return AndSpecification(self, other)
class Filter:
def filter(self, items, spec):
pass
class ColorSpecification(Specification):
def __init__(self, color):
self.color = color
def is_satisfied(self, item):
return item.color == self.color
class SizeSpecification(Specification):
def __init__(self, size):
self.size = size
def is_satisfied(self, item):
return item.size == self.size
class AndSpecification(Specification):
def __init__(self, spec1, spec2):
self.spec2 = spec2
self.spec1 = spec1
def is_satisfied(self, item):
return self.spec1.is_satisfied(item) and \
self.spec2.is_satisfied(item)
class BetterFilter(Filter):
def filter(self, items, spec):
for item in items:
if spec.is_satisfied(item):
yield item
APPLE = Product('Apple', Color.GREEN, Size.SMALL)
TREE = Product('Tree', Color.GREEN, Size.LARGE)
HOUSE = Product('House', Color.BLUE, Size.LARGE)
PRODUCTS = [APPLE, TREE, HOUSE]
PF = ProductFilter()
print("Green products (old):")
for p in PF.filter_by_color(PRODUCTS, Color.GREEN):
print(f' - {p.name} is green')
BF = BetterFilter()
print("Green products (new):")
GREEN = ColorSpecification(Color.GREEN)
for p in BF.filter(PRODUCTS, GREEN):
print(f' - {p.name} is green')
print("Large products:")
LARGE = SizeSpecification(Size.LARGE)
for p in BF.filter(PRODUCTS, LARGE):
print(f' - {p.name} is large')
print("Large blue items:")
# large_blue = AndSpecification(large, ColorSpecification(Color.BLUE))
# using python's and
large_blue = LARGE and ColorSpecification(Color.BLUE)
for p in BF.filter(PRODUCTS, large_blue):
print(f' - {p.name} is large and blue')