前言
上篇介绍了MyBatis源码中对设计模式的应用,这篇我们继续!(纯属废话,但这是我的一个写作模板,不写点总觉得怪怪的)
迭代器模式
介绍:该模式属于行为型,依赖一个迭代器的接口,顺序访问对象各个元素而不暴露内部细节,也就是对遍历进行封装
迭代器模式典型特征就是实现了Iterator接口,该模式的核心诉求是围绕着遍历来实现的,MyBatis源码中对CursorIterator,PropertyTokenizer的遍历就用到了迭代器模式
private class CursorIterator implements Iterator<T> {
/**
* Holder for the next object to be returned.
*/
T object;
/**
* Index of objects returned using next(), and as such, visible to users.
*/
int iteratorIndex = -1;
/**
* 自己来实现是否有下一个数据的依据
* @return true or false
*/
@Override
public boolean hasNext() {
if (object == null) {
object = fetchNextUsingRowBound();
}
return object != null;
}
/**
* 自己来实现获取下一个数据的依据
* @return value
*/
@Override
public T next() {
// Fill next with object fetched from hasNext()
T next = object;
if (next == null) {
next = fetchNextUsingRowBound();
}
if (next != null) {
object = null;
iteratorIndex++;
return next;
}
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException("Cannot remove element from Cursor");
}
}
模板模式
介绍:该模式属于行为型,继承复用思想,将具体的实现延迟到子类来实现
**
这种平常见的多,工作中也用的多,一般的使用方式是定义一个接口骨架,让抽象类实现它初始化通用代码,再让具体的子类来完成不同的实现。
/**
* 提供一个基本骨架
*/
public interface Executor {
// 省略好多代码...
ResultHandler NO_RESULT_HANDLER = null;
int update(MappedStatement ms, Object parameter) throws SQLException;
}
/**
* 初始化一些通用代码
*/
public abstract class BaseExecutor implements Executor {
// 省略好多代码...
@Override
public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
clearLocalCache();
return doUpdate(ms, parameter);
}
// 延迟到子类去是实现
protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;
// 省略好多代码...
}
/**
* 具体的子类展开具体的实现
*/
public class SimpleExecutor extends BaseExecutor {
/**
* 在子类中实现具体逻辑
*/
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}
// 省略好多代码...
}
组合模式
介绍:该模式属于结构型,将对象组合成树结构来体现整体和部份的关系,能够以一致的方式来处理部份和整体
这个听起来有点绕,摘抄了《Head First设计模式》中的一张图,MyBatis中SqlNode是根节点,它的所有实现类可以算是子节点,由此来实现动态SQL,可以任意加入节点,而不影响整体,可插可拔,非常方便。
/**
* 根节点
*/
public interface SqlNode {
boolean apply(DynamicContext context);
}
/**
* 子节点 <choose> 标签
*/
public class ChooseSqlNode implements SqlNode {
// 省略好多代码...
@Override
public boolean apply(DynamicContext context) {
for (SqlNode sqlNode : ifSqlNodes) {
if (sqlNode.apply(context)) {
return true;
}
}
if (defaultSqlNode != null) {
defaultSqlNode.apply(context);
return true;
}
return false;
}
}
/**
* 子节点 <if> 标签
*/
public class IfSqlNode implements SqlNode {
// 省略好多代码...
@Override
public boolean apply(DynamicContext context) {
if (evaluator.evaluateBoolean(test, context.getBindings())) {
contents.apply(context);
return true;
}
return false;
}
}
小结
对于设计模式看起来简单,但每一种设计思想光看会了还不行,最好找到其典型应用代码,自己抄一遍或者两遍,才能体会到精妙所在。所以:
一定要动手写写写代码!!!
参考
请你相信我所说的都是错的