-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsrc.com.solid.OP.java
146 lines (118 loc) · 3.33 KB
/
src.com.solid.OP.java
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
package src.com.solid.OP;
import java.util.List;
import java.util.stream.Stream;
enum Color
{
RED, GREEN, BLUE
}
enum Size
{
SMALL, MEDIUM, LARGE, YUGE
}
class Product
{
public String name;
public Color color;
public Size size;
public Product(String name, Color color, Size size) {
this.name = name;
this.color = color;
this.size = size;
}
}
class ProductFilter
{
public Stream<Product> filterByColor(List<Product> products, Color color)
{
return products.stream().filter(p -> p.color == color);
}
public Stream<Product> filterBySize(List<Product> products, Size size)
{
return products.stream().filter(p -> p.size == size);
}
public Stream<Product> filterBySizeAndColor(List<Product> products, Size size, Color color)
{
return products.stream().filter(p -> p.size == size && p.color == color);
}
// state space explosion
// 3 criteria = 7 methods
}
// we introduce two new interfaces that are open for extension
interface Specification<T>
{
boolean isSatisfied(T item);
}
interface Filter<T>
{
Stream<T> filter(List<T> items, Specification<T> spec);
}
class ColorSpecification implements Specification<Product>
{
private Color color;
public ColorSpecification(Color color) {
this.color = color;
}
@Override
public boolean isSatisfied(Product p) {
return p.color == color;
}
}
class SizeSpecification implements Specification<Product>
{
private Size size;
public SizeSpecification(Size size) {
this.size = size;
}
@Override
public boolean isSatisfied(Product p) {
return p.size == size;
}
}
class AndSpecification<T> implements Specification<T>
{
private Specification<T> first, second;
public AndSpecification(Specification<T> first, Specification<T> second) {
this.first = first;
this.second = second;
}
@Override
public boolean isSatisfied(T item) {
return first.isSatisfied(item) && second.isSatisfied(item);
}
}
class BetterFilter implements Filter<Product>
{
@Override
public Stream<Product> filter(List<Product> items, Specification<Product> spec) {
return items.stream().filter(p -> spec.isSatisfied(p));
}
}
class OCPDemo
{
public static void main(String[] args) {
Product apple = new Product("Apple", Color.GREEN, Size.SMALL);
Product tree = new Product("Tree", Color.GREEN, Size.LARGE);
Product house = new Product("House", Color.BLUE, Size.LARGE);
List<Product> products = List.of(apple, tree, house);
ProductFilter pf = new ProductFilter();
System.out.println("Green products (old):");
pf.filterByColor(products, Color.GREEN)
.forEach(p -> System.out.println(" - " + p.name + " is green"));
// ^^ BEFORE
// vv AFTER
BetterFilter bf = new BetterFilter();
System.out.println("Green products (new):");
bf.filter(products, new ColorSpecification(Color.GREEN))
.forEach(p -> System.out.println(" - " + p.name + " is green"));
System.out.println("Large products:");
bf.filter(products, new SizeSpecification(Size.LARGE))
.forEach(p -> System.out.println(" - " + p.name + " is large"));
System.out.println("Large blue items:");
bf.filter(products,
new AndSpecification<>(
new ColorSpecification(Color.BLUE),
new SizeSpecification(Size.LARGE)
))
.forEach(p -> System.out.println(" - " + p.name + " is large and blue"));
}
}