前言

上篇介绍了MyBatis源码中对设计模式的应用,这篇我们继续!(纯属废话,但这是我的一个写作模板,不写点总觉得怪怪的)

迭代器模式

介绍:该模式属于行为型,依赖一个迭代器的接口,顺序访问对象各个元素而不暴露内部细节,也就是对遍历进行封装

迭代器模式典型特征就是实现了Iterator接口,该模式的核心诉求是围绕着遍历来实现的,MyBatis源码中对CursorIterator,PropertyTokenizer的遍历就用到了迭代器模式

  1. private class CursorIterator implements Iterator<T> {
  2. /**
  3. * Holder for the next object to be returned.
  4. */
  5. T object;
  6. /**
  7. * Index of objects returned using next(), and as such, visible to users.
  8. */
  9. int iteratorIndex = -1;
  10. /**
  11. * 自己来实现是否有下一个数据的依据
  12. * @return true or false
  13. */
  14. @Override
  15. public boolean hasNext() {
  16. if (object == null) {
  17. object = fetchNextUsingRowBound();
  18. }
  19. return object != null;
  20. }
  21. /**
  22. * 自己来实现获取下一个数据的依据
  23. * @return value
  24. */
  25. @Override
  26. public T next() {
  27. // Fill next with object fetched from hasNext()
  28. T next = object;
  29. if (next == null) {
  30. next = fetchNextUsingRowBound();
  31. }
  32. if (next != null) {
  33. object = null;
  34. iteratorIndex++;
  35. return next;
  36. }
  37. throw new NoSuchElementException();
  38. }
  39. @Override
  40. public void remove() {
  41. throw new UnsupportedOperationException("Cannot remove element from Cursor");
  42. }
  43. }

模板模式

介绍:该模式属于行为型,继承复用思想,将具体的实现延迟到子类来实现
**
这种平常见的多,工作中也用的多,一般的使用方式是定义一个接口骨架,让抽象类实现它初始化通用代码,再让具体的子类来完成不同的实现。
04-设计模式-模板模式.png

  1. /**
  2. * 提供一个基本骨架
  3. */
  4. public interface Executor {
  5. // 省略好多代码...
  6. ResultHandler NO_RESULT_HANDLER = null;
  7. int update(MappedStatement ms, Object parameter) throws SQLException;
  8. }
  1. /**
  2. * 初始化一些通用代码
  3. */
  4. public abstract class BaseExecutor implements Executor {
  5. // 省略好多代码...
  6. @Override
  7. public int update(MappedStatement ms, Object parameter) throws SQLException {
  8. ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
  9. if (closed) {
  10. throw new ExecutorException("Executor was closed.");
  11. }
  12. clearLocalCache();
  13. return doUpdate(ms, parameter);
  14. }
  15. // 延迟到子类去是实现
  16. protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;
  17. // 省略好多代码...
  18. }
  1. /**
  2. * 具体的子类展开具体的实现
  3. */
  4. public class SimpleExecutor extends BaseExecutor {
  5. /**
  6. * 在子类中实现具体逻辑
  7. */
  8. @Override
  9. public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
  10. Statement stmt = null;
  11. try {
  12. Configuration configuration = ms.getConfiguration();
  13. StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
  14. stmt = prepareStatement(handler, ms.getStatementLog());
  15. return handler.update(stmt);
  16. } finally {
  17. closeStatement(stmt);
  18. }
  19. }
  20. // 省略好多代码...
  21. }

组合模式

介绍:该模式属于结构型,将对象组合成树结构来体现整体和部份的关系,能够以一致的方式来处理部份和整体

这个听起来有点绕,摘抄了《Head First设计模式》中的一张图,MyBatis中SqlNode是根节点,它的所有实现类可以算是子节点,由此来实现动态SQL,可以任意加入节点,而不影响整体,可插可拔,非常方便。

05-设计模式-组合模式.png

  1. /**
  2. * 根节点
  3. */
  4. public interface SqlNode {
  5. boolean apply(DynamicContext context);
  6. }
  7. /**
  8. * 子节点 <choose> 标签
  9. */
  10. public class ChooseSqlNode implements SqlNode {
  11. // 省略好多代码...
  12. @Override
  13. public boolean apply(DynamicContext context) {
  14. for (SqlNode sqlNode : ifSqlNodes) {
  15. if (sqlNode.apply(context)) {
  16. return true;
  17. }
  18. }
  19. if (defaultSqlNode != null) {
  20. defaultSqlNode.apply(context);
  21. return true;
  22. }
  23. return false;
  24. }
  25. }
  26. /**
  27. * 子节点 <if> 标签
  28. */
  29. public class IfSqlNode implements SqlNode {
  30. // 省略好多代码...
  31. @Override
  32. public boolean apply(DynamicContext context) {
  33. if (evaluator.evaluateBoolean(test, context.getBindings())) {
  34. contents.apply(context);
  35. return true;
  36. }
  37. return false;
  38. }
  39. }

小结

对于设计模式看起来简单,但每一种设计思想光看会了还不行,最好找到其典型应用代码,自己抄一遍或者两遍,才能体会到精妙所在。所以:
一定要动手写写写代码!!!

参考

请你相信我所说的都是错的