[設計模式] 構造者模式
阿新 • • 發佈:2018-11-09
構造者模式
引用文章
前言
一般在封裝實體類時我們通常會用構造方法等形式往實體類傳遞引數,有可能對不同個數的引數進行初始化,你會定義出不同的構造方法,當然這都沒問題,如果是當前實體類中的引數過於多時,這時候再用構造方法傳遞引數會有點力不從心,很大程度不會影響程式碼的可讀性與美觀性。那這個時候構造者模式的出現完美的解決這一問題。
構造者模式的出現很好的解決了多引數初始化的問題。我簡單寫個例子用來構造一個網路請求地址的實體類,帶大家簡單瞭解下什麼是構造者模式。
示例
public class ParamsBuilder {
private String url;
private String password;
private String username;
public String getUrl() {
return url;
}
public String getPassword() {
return password;
}
public String getUsername() {
return username;
}
public static class Builder {
private String url = null;
private String password = null;
private String username = null;
public Builder url(String url) {
this.url = url;
return this;
}
public Builder username(String username) {
this .username = username;
return this;
}
public Builder password(String password) {
this.password = password;
return this;
}
public ParamsBuilder builder() {
return new ParamsBuilder(this);
}
}
private ParamsBuilder(Builder b) {
url = b.url;
password = b.password;
username = b.username;
}
@Override
public String toString() {
return "ParamsBuilder " + url + "/?username=" + username + "?password=" + password;
}
}
初始化的時候
ParamsBuilder params = new ParamsBuilder.Builder()
.url("wwww.baidu.com")
.username("xie")
.password("123")
.builder();
MyBatis中用構造者模式的類
org.apache.ibatis.mapping.ParameterMapping
在build的時,進行了引數的校驗。
此外,org.apache.ibatis.mapping
包下有大量的類用到了構造者模式。
public class ParameterMapping {
private Configuration configuration;
private String property;
private ParameterMode mode;
private Class<?> javaType = Object.class;
private JdbcType jdbcType;
private Integer numericScale;
private TypeHandler<?> typeHandler;
private String resultMapId;
private String jdbcTypeName;
private String expression;
private ParameterMapping() {
}
public static class Builder {
private ParameterMapping parameterMapping = new ParameterMapping();
public Builder(Configuration configuration, String property, TypeHandler<?> typeHandler) {
parameterMapping.configuration = configuration;
parameterMapping.property = property;
parameterMapping.typeHandler = typeHandler;
parameterMapping.mode = ParameterMode.IN;
}
public Builder(Configuration configuration, String property, Class<?> javaType) {
parameterMapping.configuration = configuration;
parameterMapping.property = property;
parameterMapping.javaType = javaType;
parameterMapping.mode = ParameterMode.IN;
}
public Builder mode(ParameterMode mode) {
parameterMapping.mode = mode;
return this;
}
public Builder javaType(Class<?> javaType) {
parameterMapping.javaType = javaType;
return this;
}
public Builder jdbcType(JdbcType jdbcType) {
parameterMapping.jdbcType = jdbcType;
return this;
}
...
public ParameterMapping build() {
resolveTypeHandler();
validate();
return parameterMapping;
}
private void validate() {
if (ResultSet.class.equals(parameterMapping.javaType)) {
if (parameterMapping.resultMapId == null) {
throw new IllegalStateException("Missing resultmap in property '"
+ parameterMapping.property + "'. "
+ "Parameters of type java.sql.ResultSet require a resultmap.");
}
} else {
if (parameterMapping.typeHandler == null) {
throw new IllegalStateException("Type handler was null on parameter mapping for property '"
+ parameterMapping.property + "'. It was either not specified and/or could not be found for the javaType ("
+ parameterMapping.javaType.getName() + ") : jdbcType (" + parameterMapping.jdbcType + ") combination.");
}
}
}
private void resolveTypeHandler() {
if (parameterMapping.typeHandler == null && parameterMapping.javaType != null) {
Configuration configuration = parameterMapping.configuration;
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
parameterMapping.typeHandler = typeHandlerRegistry.getTypeHandler(parameterMapping.javaType, parameterMapping.jdbcType);
}
}