人的知识就好比一个圆圈,圆圈里面是已知的,圆圈外面是未知的。你知道得越多,圆圈也就越大,你不知道的也就越多。

0%

设计模式--建造者模式

定义

建造者模式封装一个产品的构造过程,并允许按步骤构造。

角色

  • 抽象建造者(Builder):用于规范产品的各个组成部分,并进行抽象,一般独立于应用程序的逻辑。
  • 具体建造者(Concrete Builder):实现抽象建造者中定义的所有方法,并且返回一个组建好的产品实例。
  • 产品(Product):建造者模式中的复杂对象,一个系统中会有多于一个的产品类,这些产品类并不一定有共同的接口,完全可以是不相关联的。
  • 导演者(Director):负责安排已有模块的顺序,然后告诉Builder开始建造。

类图

Builder UML

优缺点

优点

  • 使用建造者模式可以使客户端不必知道产品内部组成的细节
  • 具体的建造者类之间是相互独立的,这有利于系统的扩展
  • 具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响

缺点

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大

适用场景

  • 需要生成的对象具有复杂的内部结构
  • 需要生成的对象内部属性本身相互依赖

实现

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
/**
* 方式一
*/
public class ProductBuilder {
private Product product;

public ProductBuilder() {
this.product = new Product();
}

public Product buildPartA(String partA) {
product.setPartA(partA);
return this.product;
}

public Product buildPartB(String partB) {
product.setPartB(partB);
return this.product;
}

public Product buildPartC(String partC) {
product.setPartC(partC);
return this.product;
}

public Product build() {
return this.product;
}
}

/**
* 方式二
*/
public class ProductBuilder {
private Product product;

public ProductBuilder() {
this.product = new Product();
}

public ProductBuilder buildPartA(String partA) {
product.setPartA(partA);
return this;
}

public ProductBuilder buildPartB(String partB) {
product.setPartB(partB);
return this;
}

public ProductBuilder buildPartC(String partC) {
product.setPartC(partC);
return this;
}

public Product build() {
return this.product;
}
}

模式应用

Spring Data ElasticSearch中大量使用了建造者模式,以IndexQueryBuilder为例:

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
public class IndexQueryBuilder {
private String id;
private Object object;
private Long version;
private String indexName;
private String type;
private String source;
private String parentId;

public IndexQueryBuilder() {
}

public IndexQueryBuilder withId(String id) {
this.id = id;
return this;
}

public IndexQueryBuilder withObject(Object object) {
this.object = object;
return this;
}

public IndexQueryBuilder withVersion(Long version) {
this.version = version;
return this;
}

public IndexQueryBuilder withIndexName(String indexName) {
this.indexName = indexName;
return this;
}

public IndexQueryBuilder withType(String type) {
this.type = type;
return this;
}

public IndexQueryBuilder withSource(String source) {
this.source = source;
return this;
}

public IndexQueryBuilder withParentId(String parentId) {
this.parentId = parentId;
return this;
}

public IndexQuery build() {
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(this.id);
indexQuery.setIndexName(this.indexName);
indexQuery.setType(this.type);
indexQuery.setObject(this.object);
indexQuery.setParentId(this.parentId);
indexQuery.setSource(this.source);
indexQuery.setVersion(this.version);
return indexQuery;
}
}

实际应用

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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
public class ExportDefinition {
/**
* 每张表最多只能存储1048576行数据
*/
public static final int MAX_ROW = 1048576;

/**
* 表名
*/
private String sheetName;

/**
* 标题定义
*/
private TitleDefinition title;

/**
* label定义列表
*/
private List<LabelDefinition> labels;

/**
* 属性定义列表
*/
private List<PropertyDefinition> properties;

/**
* 子定义列表(适用于子表)
*/
private List<ExportDefinition> childrenDefinitions;

/**
* 主题函数工厂(函数接受一个Workbook并返回一个CellStyle)
*/
private StyleFunctionFactory styleFunctionFactory;

/**
* 内存中数据量达到多少时刷新
*/
private int windowSize;

/**
* 是否压缩临时excel
*/
private boolean compress;

/**
* 打包导出时,每个excel的最大存储数据量
*/
private int packageSize;

private ExportDefinition(Builder builder) {
this.sheetName = builder.sheetName;
this.title = builder.title;
this.labels = builder.labels;
this.properties = builder.properties;
this.childrenDefinitions = builder.childrenDefinitions;
this.styleFunctionFactory = builder.styleFunctionFactory;
this.windowSize = builder.windowSize;
this.compress = builder.compress;
this.packageSize = builder.packageSize;

if (this.title != null) {
this.title.setWidth(this.properties.size());
}
}

public String getSheetName() {
return sheetName;
}

public TitleDefinition getTitle() {
return title;
}

public List<LabelDefinition> getLabels() {
return labels;
}

public List<PropertyDefinition> getProperties() {
return properties;
}

public List<ExportDefinition> getChildrenDefinitions() {
return childrenDefinitions;
}

public StyleFunctionFactory getStyleFunctionFactory() {
return styleFunctionFactory;
}

public int getWindowSize() {
return windowSize;
}

public boolean isCompress() {
return compress;
}

public int getPackageSize() {
return packageSize;
}

/**
* 返回表头高度
*/
public int getHeaderHeight() {
return labels.stream().map(LabelDefinition::getHeight).max(Integer::compareTo).orElse(0);
}

/**
* 返回表头宽度
*/
public int getHeaderWidth() {
return labels.stream().map(LabelDefinition::getWidth).max(Integer::compareTo).orElse(0);
}

/**
* 返回表头起始行索引
*/
public int getHeaderBeginRowIndex() {
return getTitle() == null ? 0 : getTitle().getHeight() + 1;
}

/**
* 返回数据起始行索引
*/
public int getDataBeginRowIndex() {
return getHeaderBeginRowIndex() + getHeaderHeight();
}

/**
* 构造器
*/
public static class Builder {
private String sheetName;

private TitleDefinition title;

private List<LabelDefinition> labels;

private List<PropertyDefinition> properties;

private List<ExportDefinition> childrenDefinitions;

/**
* 没有定义主题函数工厂,就使用默认的
*/
private StyleFunctionFactory styleFunctionFactory = new DefaultStyleFunctionFactory();

/**
* 内存中数据量达到100就刷新
*/
private int windowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE;

/**
* 默认不压缩临时excel
*/
private boolean compress;

/**
* 打包导出时,默认每个excel的最大存储数据量为200000
*/
private int packageSize = 200000;

public Builder sheetName(String sheetName) {
this.sheetName = sheetName;
return this;
}

public Builder title(TitleDefinition title) {
this.title = title;
return this;
}

public Builder labels(List<LabelDefinition> labels) {
this.labels = labels;
return this;
}

public Builder properties(List<PropertyDefinition> properties) {
this.properties = properties;
return this;
}

public Builder childrenDefinitions(List<ExportDefinition> childrenDefinitions) {
this.childrenDefinitions = childrenDefinitions;
return this;
}

public Builder styleFunctionFactory(StyleFunctionFactory functionFactory) {
this.styleFunctionFactory = functionFactory;
return this;
}

public Builder windowSize(int windowSize) {
this.windowSize = windowSize;
return this;
}

public Builder compress(boolean compress) {
this.compress = compress;
return this;
}

public Builder packageSize(int packageSize) {
this.packageSize = packageSize;
return this;
}

public Builder simpleTitle(String title) {
this.title = new TitleDefinition.Builder().name(title).height(1).build();
return this;
}

public Builder simpleLabels(List<String> labels) {
this.labels = labels.stream()
.map(label -> new LabelDefinition.Builder().name(label).build())
.collect(Collectors.toList());
return this;
}

public Builder simpleProperties(List<String> properties) {
this.properties = properties.stream()
.map(property -> new PropertyDefinition.Builder().name(property).build())
.collect(Collectors.toList());
return this;
}

public ExportDefinition build() {
if (!CollectionUtils.isEmpty(this.properties) && !CollectionUtils.isEmpty(this.labels) &&
this.properties.size() != this.labels.stream()
.map(LabelDefinition::getWidth)
.reduce((pre, cur) -> pre + cur)
.orElse(0)) {
throw new ExportException("labels属性与properties属性未一一对应");
}
return new ExportDefinition(this);
}
}
}
小礼物走一走,来 Github 关注我