设计模式-建造者(Builder)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-建造者(Builder)相关的知识,希望对你有一定的参考价值。
2018-1-18 by Atlas
- 应用场景
需要采取循序渐进组合复杂对象时。
- UML
用过elasticsearch java api的小伙伴,自然了解BoolQueryBuilder及其内部doXContext处理的对象都是Builder模式,这里BoolQuerySearchBuilder是我给其上根据业务需要又做的一层封装,也是Builder模式,形式上看就是Builder模式嵌套Builder模式。
- 标准示例
public class BoolQuerySearchBuilder extends AbstractSearchBuilder {
private final BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
public BoolQuerySearchBuilder mustQueryBuilders(List<QueryBuilder> mustQueryBuilders){
// 所有分句都必须匹配,类比 SQL 的 AND
if(mustQueryBuilders != null){
for(QueryBuilder queryBuilderTmp : mustQueryBuilders){
boolQueryBuilder.must(queryBuilderTmp);
}
}
return this;
}
public BoolQuerySearchBuilder mustNotQueryBuilders(List<QueryBuilder> mustNotQueryBuilders){
// 所有分句都必须不匹配,类比 SQL 的 NOT
if(mustNotQueryBuilders != null){
for(QueryBuilder queryBuilder : mustNotQueryBuilders){
boolQueryBuilder.mustNot(queryBuilder);
}
}
return this;
}
public BoolQuerySearchBuilder shouldQueryBuilders(List<QueryBuilder> shouldQueryBuilders){
// 至少有一个分句匹配,类比 SQL 的 OR
if(shouldQueryBuilders != null){
for(QueryBuilder queryBuilder : shouldQueryBuilders){
boolQueryBuilder.should(queryBuilder);
}
}
return this;
}
@Override
protected final QueryBuilder queryBuilder() {
return boolQueryBuilder;
}
}
- boolQueryBuilder是复杂的对象。
- mustQueryBuilders、mustNotQueryBuilder、shouldQueryBuilders分别通过调用boolQueryBuilder的must、mustNot、should循环渐进的组合boolQueryBuilder对象。
- 循环渐进组合对象过程中返回外层建造者,直到建造者完成对象组合,返回建造的对象。
public class BoolQueryBuilder extends QueryBuilder implements BoostableQueryBuilder<BoolQueryBuilder> {
private final List<QueryBuilder> mustClauses = new ArrayList<>();
private final List<QueryBuilder> mustNotClauses = new ArrayList<>();
private final List<QueryBuilder> shouldClauses = new ArrayList<>();
public BoolQueryBuilder must(QueryBuilder queryBuilder) {
mustClauses.add(queryBuilder);
return this;
}
public BoolQueryBuilder mustNot(QueryBuilder queryBuilder) {
mustNotClauses.add(queryBuilder);
return this;
}
public BoolQueryBuilder should(QueryBuilder queryBuilder) {
shouldClauses.add(queryBuilder);
return this;
}
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject("bool");
doXArrayContent("must", mustClauses, builder, params);
doXArrayContent("filter", filterClauses, builder, params);
doXArrayContent("must_not", mustNotClauses, builder, params);
doXArrayContent("should", shouldClauses, builder, params);
if (boost != -1) {
builder.field("boost", boost);
}
if (disableCoord != null) {
builder.field("disable_coord", disableCoord);
}
if (minimumShouldMatch != null) {
builder.field("minimum_should_match", minimumShouldMatch);
}
if (adjustPureNegative != null) {
builder.field("adjust_pure_negative", adjustPureNegative);
}
if (queryName != null) {
builder.field("_name", queryName);
}
builder.endObject();
}
// ...
}
BoolQueryBuilder对象本身也是Builder模式,循序渐进的组合追加的must、mustNot、should然后最终生成包含逻辑格式的文本Content,整个过程就是elasticsearch根据查询条件动态生成查询命令文本的过程。
- 调用方具体执行对象建造如下:
public JSONObject search(JSONObject jsonObject) throws Exception {
logger.info("elasticsearch request json data : [{}]", jsonObject.toString());
// ...
// 通过建造者生成查询命令,循序渐进组合对象不仅代码整洁而且过程灵活多变
SearchBuilder searchBuilder = new BoolQuerySearchBuilder()
.shouldQueryBuilders(shouldQueryBuilders(jsonObject))
.mustQueryBuilders(mustQueryBuilders(jsonObject))
.mustNotQueryBuilders(mustNotQueryBuilders(jsonObject));
// 根据查询命令执行elasticsearch搜索并响应搜索结果
Map<String, Object> map = searchBuilder.mutiSearch(indexName, indexType, currentPage, pageSize);
// ...
logger.info("elasticsearch response json data : [{}]", data.toJSONString());
return data;
}
- 案例鉴赏
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
// ...
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
@Override
public StringBuilder append(CharSequence s, int start, int end) {
super.append(s, start, end);
return this;
}
@Override
public StringBuilder append(char[] str) {
super.append(str);
return this;
}
// ...
@Override
public String toString() {
// 通过循序渐进组合追加的字符数组,创建String对象
return new String(value, 0, count);
}
}
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* 字符数组.
*/
char[] value;
// ...
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null)
return appendNull();
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
count += len;
return this;
}
@Override
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
s = "null";
if ((start < 0) || (start > end) || (end > s.length()))
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() "
+ s.length());
int len = end - start;
ensureCapacityInternal(count + len);
for (int i = start, j = count; i < end; i++, j++)
value[j] = s.charAt(i);
count += len;
return this;
}
public AbstractStringBuilder append(char[] str) {
int len = str.length;
ensureCapacityInternal(count + len);
System.arraycopy(str, 0, value, count, len);
count += len;
return this;
}
public AbstractStringBuilder append(char c) {
ensureCapacityInternal(count + 1);
value[count++] = c;
return this;
}
// ...
}
StringBuilder的append方法调用基类AbstractStringBuilder的append方法向value字符数组追加字符,最终通过value字符数组完成String对象的创建。
以上是关于设计模式-建造者(Builder)的主要内容,如果未能解决你的问题,请参考以下文章