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