2018-1-18 by Atlasjava
将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具备不一样的内部表象的产品对象。建造模式使得产品内部表象能够独立的变化,客户没必要知道产品内部组成的细节。建造模式能够强制实行一种分步骤进行的建造过程。json
须要采起按部就班组合复杂对象时。api
- Builder(建造者)参与者
Builder参与者是规定产生对象实例的接口。包括产生对象实例各个部分的方法和取得最后的结果的方法。- ConcreteBuilder(具体建造者)参与者
ConcreteBuilder参与者是实现Builder参与者的接口的类。在实际产生对象实例时所调用的方法就是在这里定义的。- Director(监工)参与者
Director参与者利用Builder参与者的接口产生对象实例。设计程序时必须注意不要被ConcreteBuilder参与者牵着鼻子走。为了让ConcreteBuilder参与者不管在什么情形之下都能正常发挥功能,因此只使用Builder参与者的方法。- Client(客户)参与者
利用Builder Pattern的参与者。
用过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根据查询条件动态生成查询命令文本的过程。app
- 调用方具体执行对象建造以下:
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对象的建立。elasticsearch