MyBatis框架有多处使用了设计模式,我们在阅读其源码时,需要好好体会它对设计模式的使用,以便于照着葫芦画瓢。本篇主要是记录一下适配器模式的使用。
适配器模式理解起来很简单,相当于使用了一个接口,将老旧的功能包装一下,使之适应新的需求(或许有错误,但错就错吧)。
MyBatis框架对适配器的使用,主要体现在Log日志这一块。
MyBatis自个定义了一个Log接口,接口嘛,规范而已。 而具体要怎么操作我不管,只需要按照我的规范来即可。
/** * MyBatis定义的日志接口规范 */ public interface Log { boolean isDebugEnabled(); boolean isTraceEnabled(); void error(String s, Throwable e); void error(String s); void debug(String s); void trace(String s); void warn(String s); }
该接口定义了Mybatis直接使用的日志方法,而Log接口具体由谁来实现呢?Mybatis提供了多种日志框架的实现,这些实现都匹配这个Log接口所定义的接口方法,最终实现了所有外部日志框架到Mybatis日志包的适配。
MyBatis就是这么刚,提供了如此之多实现方式。 啥意思呢,就是Log接口适配了这么多的日志框架, 我们在使用时,只需要随便引入其中一种日志框架,那么就可以使用Log接口规范去操作日志了。
下面我们来看一个具体的实现。 毕竟接口是啥事都干不了的,干事还得靠实现啦!
以log4j为例
import org.apache.ibatis.logging.Log; import org.apache.log4j.Level; import org.apache.log4j.Logger; public class Log4jImpl implements Log { private static final String FQCN = Log4jImpl.class.getName(); // 将log4j框架的日志实例对象定义成全局变量,以便于类中其它方法操作 private final Logger log; /** * 通过构造创建真正的日志操作实例,此处是apache的log4j */ public Log4jImpl(String clazz) { log = Logger.getLogger(clazz); // 真正干事的东西 } /** * 调用MyBatis的Log接口方法isDebugEnabled,其实质就是调用apache log4j日志对象的isDebugEnabled方法 * 其它方法也是一样原理 */
@Override public boolean isDebugEnabled() { return log.isDebugEnabled(); } @Override public boolean isTraceEnabled() { return log.isTraceEnabled(); } @Override public void error(String s, Throwable e) { log.log(FQCN, Level.ERROR, s, e); } @Override public void error(String s) { log.log(FQCN, Level.ERROR, s, null); } @Override public void debug(String s) { log.log(FQCN, Level.DEBUG, s, null); } @Override public void trace(String s) { log.log(FQCN, Level.TRACE, s, null); } @Override public void warn(String s) { log.log(FQCN, Level.WARN, s, null); } }
再比如另一个实现适配jdk日志
import java.util.logging.Level; import java.util.logging.Logger; import org.apache.ibatis.logging.Log; /** * @author Clinton Begin */ public class Jdk14LoggingImpl implements Log { private final Logger log; public Jdk14LoggingImpl(String clazz) { log = Logger.getLogger(clazz); // 真正干事的东西 } @Override public boolean isDebugEnabled() { return log.isLoggable(Level.FINE); } @Override public boolean isTraceEnabled() { return log.isLoggable(Level.FINER); } @Override public void error(String s, Throwable e) { log.log(Level.SEVERE, s, e); } @Override public void error(String s) { log.log(Level.SEVERE, s); } @Override public void debug(String s) { log.log(Level.FINE, s); } @Override public void trace(String s) { log.log(Level.FINER, s); } @Override public void warn(String s) { log.log(Level.WARNING, s); } }
代码很简单,原理也是一样一样的。
总结:
适配器模式就是这么简单,代码套路就是先创建一个接口,接口的各种实现子类裹挟着真正干事的的对象。为啥叫适配器模式呢?估计就是通过这个接口将调用方与真正干事的实例关联起来。是不是感觉有点解耦的意味? 我觉得有那么点意思,但其实质还是将多种干事儿的实例,通过一个接口进行规范,以方便调用方的使用。 即是,调用方不必关心具体的实现。
是不是觉得有点像门面模式,其实不是哟!
是不是觉得有点像策略模式,我觉得有那么点意味。。。。但还是有差别。