今天學mybatis的時候,知道了SQLSessionFactory使用的是builder模式來生成的。再次整理一下什麼是builder模式以及應用場景。java
builder模式也叫建造者模式,builder模式的做用將一個複雜對象的構建與他的表示分離,使用者能夠一步一步的構建一個比較複雜的對象。設計模式
咱們一般構造一個有不少參數的對象時有三種方式:構造器重載,JavaBeans模式和builder模式。經過一個小例子咱們來看一下builder模式的優點。mybatis
package com.wangjun.designPattern.builder; public class Product { private int id; private String name; private int type; private float price; public Product() { super(); } public Product(int id) { super(); this.id = id; } public Product(int id, String name) { super(); this.id = id; this.name = name; } public Product(int id, String name, int type) { super(); this.id = id; this.name = name; this.type = type; } public Product(int id, String name, int type, float price) { super(); this.id = id; this.name = name; this.type = type; this.price = price; } }
使用構造器重載咱們須要定義不少構造器,爲了應對使用者不一樣的需求(有些可能只須要id,有些須要id和name,有些只須要name,......),理論上咱們須要定義2^4 = 16個構造器,這只是4個參數,若是參數更多的話,那將是指數級增加,確定是不合理的。要麼你定義一個所有參數的構造器,使用者只能多傳入一些不須要的屬性值來匹配你的構造器。很明顯這種構造器重載的方式對於多屬性的狀況是不完美的。ui
package com.wangjun.designPattern.builder; public class Product2 { private int id; private String name; private int type; private float price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getType() { return type; } public void setType(int type) { this.type = type; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
JavaBeans方式就是提供setter方法,在使用的時候根據需求先調用無參構造器再調用setter方法填充屬性值。this
Product2 p2 = new Product2(); p2.setId(10); p2.setName("phone"); p2.setPrice(100); p2.setType(1);
這種方式彌補了構造器重載的不足,建立實例很容易,代碼讀起來也很容易。可是,由於構造過程被分到了幾個調用中,在構造過程當中JavaBeans可能處於不一致的狀態,類沒法僅僅經過檢驗構造器參數的有效性來保證一致性。設計
package com.wangjun.designPattern.builder; public class Product3 { private final int id; private final String name; private final int type; private final float price; private Product3(Builder builder) { this.id = builder.id; this.name = builder.name; this.type = builder.type; this.price = builder.price; } public static class Builder { private int id; private String name; private int type; private float price; public Builder id(int id) { this.id = id; return this; } public Builder name(String name) { this.name = name; return this; } public Builder type(int type) { this.type = type; return this; } public Builder price(float price) { this.price = price; return this; } public Product3 build() { return new Product3(this); } } }
能夠看到builder模式將屬性定義爲不可變的,而後定義一個內部靜態類Builder來構建屬性,再經過一個只有Builder參數的構造器來生成Product對象。Builder的setter方法返回builder自己,以即可以將屬性鏈接起來。咱們就能夠像下面這樣使用了。code
Product3 p3 = new Product3.Builder() .id(10) .name("phone") .price(100) .type(1) .build();
固然具體使用builder的狀況確定沒有這麼簡單,可是思路大體同樣:先經過某種方式取得構造對象須要的全部參數,再經過這些參數一次性構建這個對象。好比MyBatis中SqlSessionFactoryBuilder就是經過讀取MyBatis的xml配置文件來獲取構造SqlSessionFactory所須要的參數的。xml