当一个类的成员熟悉过于复杂,庞大时,考虑用建造者模式来设计类。如果你在源码中看到一堆方法通过“·”连接,最后调用build()方法,那他就是在用建造者模式构建一个对象了。直接上源码。
Mybatis解析配置文件之解析mapper.xml文件,将它解析成一个MapperStatement对象供后续使用
看一下这个MapperStatement类
public final class MappedStatement {
private String resource;
private Configuration configuration;
private String id;
private Integer fetchSize;
private Integer timeout;
private StatementType statementType;
private ResultSetType resultSetType;
private SqlSource sqlSource;
private Cache cache;
private ParameterMap parameterMap;
private List<ResultMap> resultMaps;
private boolean flushCacheRequired;
private boolean useCache;
private boolean resultOrdered;
private SqlCommandType sqlCommandType;
private KeyGenerator keyGenerator;
private String[] keyProperties;
private String[] keyColumns;
private boolean hasNestedResultMaps;
private String databaseId;
private Log statementLog;
private LanguageDriver lang;
private String[] resultSets;
}
这么多属性,除了一些必备的属性每次需要初始化,其他的属性只有需要时才会给他初始化。看下它是怎么处理的。在MapperStatement类里有一个内部类Builder ,它的构造方法会给一些必备的属性赋值,非必须的属性我提供一个赋值的方法,注意返回的是this对象。利用的就是这个this对象,我调用了第一个赋值方法后返回的是this,这就方便了,直接接着后面通过’.’(点)调用第二个赋值方法。
public final class MappedStatement {
private String resource;
private Configuration configuration;
.........
.........
public static class Builder {
//属性赋值都是给这个mappedStatement 对象,将来就是将它返回来达到构建mappedStatement 对象的目的
private MappedStatement mappedStatement = new MappedStatement();
//构造方法统一给必备属性赋值
public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
mappedStatement.configuration = configuration;
mappedStatement.id = id;
mappedStatement.sqlSource = sqlSource;
mappedStatement.statementType = StatementType.PREPARED;
mappedStatement.resultSetType = ResultSetType.DEFAULT;
...........
...........
}
//非必须的属性我提供一个赋值的方法,注意返回的是this对象
public Builder resource(String resource) {
mappedStatement.resource = resource;
return this;
}
public String id() {
return mappedStatement.id;
}
public Builder parameterMap(ParameterMap parameterMap) {
mappedStatement.parameterMap = parameterMap;
return this;
}
public Builder fetchSize(Integer fetchSize) {
mappedStatement.fetchSize = fetchSize;
return this;
}
...............
...............
//调用build()就返回mappedStatement
public MappedStatement build() {
return mappedStatement;
}
}
}
构建MapperStatement对象
MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
.resource(resource)
.fetchSize(fetchSize)
.timeout(timeout)
.statementType(statementType)
.keyGenerator(keyGenerator)
.keyProperty(keyProperty)
.keyColumn(keyColumn)
.databaseId(databaseId)
.................
.................
//调用内部类的builder()拿到最终的MappedStatement
MappedStatement statement = statementBuilder.build();
完事
idea里面由自动建造者模式的插件 Builder Generate ,安装重启后右键-Generate -builder-勾选inner builder,生成的代码思路是和这里一样的。(不要陷入死代码了,核心是思路)