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