Skip to content

Commit ccf7c2a

Browse files
Open-Closed Principle
1 parent ef29037 commit ccf7c2a

File tree

1 file changed

+129
-0
lines changed
  • src/1_patterns/1_SOLIDDesignPrinciples/2_Open-Closed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
from enum import Enum
2+
3+
4+
class Color(Enum):
5+
RED = 1
6+
GREEN = 2
7+
BLUE = 3
8+
9+
10+
class Size(Enum):
11+
SMALL = 1
12+
MEDIUM = 2
13+
LARGE = 3
14+
15+
16+
class Product:
17+
def __init__(self, name, color, size):
18+
self.name = name
19+
self.color = color
20+
self.size = size
21+
22+
23+
class ProductFilter:
24+
def filter_by_color(self, products, color):
25+
for p in products:
26+
if p.color == color: yield p
27+
28+
def filter_by_size(self, products, size):
29+
for p in products:
30+
if p.size == size: yield p
31+
32+
def filter_by_size_and_color(self, products, size, color):
33+
for p in products:
34+
if p.color == color and p.size == size:
35+
yield p
36+
37+
# state space explosion
38+
# 3 criteria
39+
# c s w cs sw cw csw = 7 methods
40+
41+
# OCP = open for extension, closed for modification
42+
43+
44+
class Specification:
45+
def is_satisfied(self, item):
46+
pass
47+
48+
# and operator makes life easier
49+
def __and__(self, other):
50+
return AndSpecification(self, other)
51+
52+
53+
class Filter:
54+
def filter(self, items, spec):
55+
pass
56+
57+
58+
class ColorSpecification(Specification):
59+
def __init__(self, color):
60+
self.color = color
61+
62+
def is_satisfied(self, item):
63+
return item.color == self.color
64+
65+
66+
class SizeSpecification(Specification):
67+
def __init__(self, size):
68+
self.size = size
69+
70+
def is_satisfied(self, item):
71+
return item.size == self.size
72+
73+
74+
# class AndSpecification(Specification):
75+
# def __init__(self, spec1, spec2):
76+
# self.spec2 = spec2
77+
# self.spec1 = spec1
78+
#
79+
# def is_satisfied(self, item):
80+
# return self.spec1.is_satisfied(item) and \
81+
# self.spec2.is_satisfied(item)
82+
83+
class AndSpecification(Specification):
84+
def __init__(self, *args):
85+
self.args = args
86+
87+
def is_satisfied(self, item):
88+
return all(map(
89+
lambda spec: spec.is_satisfied(item), self.args))
90+
91+
92+
class BetterFilter(Filter):
93+
def filter(self, items, spec):
94+
for item in items:
95+
if spec.is_satisfied(item):
96+
yield item
97+
98+
99+
apple = Product('Apple', Color.GREEN, Size.SMALL)
100+
tree = Product('Tree', Color.GREEN, Size.LARGE)
101+
house = Product('House', Color.BLUE, Size.LARGE)
102+
103+
products = [apple, tree, house]
104+
105+
pf = ProductFilter()
106+
print('Green products (old):')
107+
for p in pf.filter_by_color(products, Color.GREEN):
108+
print(f' - {p.name} is green')
109+
110+
# ^ BEFORE
111+
112+
# v AFTER
113+
bf = BetterFilter()
114+
115+
print('Green products (new):')
116+
green = ColorSpecification(Color.GREEN)
117+
for p in bf.filter(products, green):
118+
print(f' - {p.name} is green')
119+
120+
print('Large products:')
121+
large = SizeSpecification(Size.LARGE)
122+
for p in bf.filter(products, large):
123+
print(f' - {p.name} is large')
124+
125+
print('Large blue items:')
126+
# large_blue = AndSpecification(large, ColorSpecification(Color.BLUE))
127+
large_blue = large & ColorSpecification(Color.BLUE)
128+
for p in bf.filter(products, large_blue):
129+
print(f' - {p.name} is large and blue')

0 commit comments

Comments
 (0)