-
Notifications
You must be signed in to change notification settings - Fork 0
/
solid.ocp.go
153 lines (113 loc) · 2.64 KB
/
solid.ocp.go
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
package main
import "fmt"
// combination of OCP and Repository demo
// open for extension, closed for modification
type Color int
const (
red Color = iota
green
blue
)
type Size int
const (
small Size = iota
medium
large
)
type Product struct {
name string
color Color
size Size
}
type Filter struct {
}
func (f *Filter) filterByColor(
products []Product, color Color)[]*Product {
result := make([]*Product, 0)
for i, v := range products {
if v.color == color {
result = append(result, &products[i])
}
}
return result
}
func (f *Filter) filterBySize(
products []Product, size Size) []*Product {
result := make([]*Product, 0)
for i, v := range products {
if v.size == size {
result = append(result, &products[i])
}
}
return result
}
func (f *Filter) filterBySizeAndColor(
products []Product, size Size,
color Color)[]*Product {
result := make([]*Product, 0)
for i, v := range products {
if v.size == size && v.color == color {
result = append(result, &products[i])
}
}
return result
}
// filterBySize, filterBySizeAndColor
type Specification interface {
IsSatisfied(p *Product) bool
}
type ColorSpecification struct {
color Color
}
func (spec ColorSpecification) IsSatisfied(p *Product) bool {
return p.color == spec.color
}
type SizeSpecification struct {
size Size
}
func (spec SizeSpecification) IsSatisfied(p *Product) bool {
return p.size == spec.size
}
type AndSpecification struct {
first, second Specification
}
func (spec AndSpecification) IsSatisfied(p *Product) bool {
return spec.first.IsSatisfied(p) &&
spec.second.IsSatisfied(p)
}
type BetterFilter struct {}
func (f *BetterFilter) Filter(
products []Product, spec Specification) []*Product {
result := make([]*Product, 0)
for i, v := range products {
if spec.IsSatisfied(&v) {
result = append(result, &products[i])
}
}
return result
}
func main() {
apple := Product{"Apple", green, small}
tree := Product{"Tree", green, large}
house := Product{ "House", blue, large}
products := []Product{apple, tree, house}
fmt.Print("Green products (old):\n")
f := Filter{}
for _, v := range f.filterByColor(products, green) {
fmt.Printf(" - %s is green\n", v.name)
}
// ^^^ BEFORE
// vvv AFTER
fmt.Print("Green products (new):\n")
greenSpec := ColorSpecification{green}
bf := BetterFilter{}
for _, v := range bf.Filter(products, greenSpec) {
fmt.Printf(" - %s is green\n", v.name)
}
largeSpec := SizeSpecification{large}
largeGreenSpec := AndSpecification{largeSpec, greenSpec}
fmt.Print("Large blue items:\n")
for _, v := range bf.Filter(products, largeGreenSpec) {
fmt.Printf(" - %s is large and green\n", v.name)
}
}