• MyBatis框架之适配器模式


    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);
      }
    
    }

    代码很简单,原理也是一样一样的。

    总结:

      适配器模式就是这么简单,代码套路就是先创建一个接口,接口的各种实现子类裹挟着真正干事的的对象。为啥叫适配器模式呢?估计就是通过这个接口将调用方与真正干事的实例关联起来。是不是感觉有点解耦的意味? 我觉得有那么点意思,但其实质还是将多种干事儿的实例,通过一个接口进行规范,以方便调用方的使用。 即是,调用方不必关心具体的实现。

      是不是觉得有点像门面模式,其实不是哟! 

      是不是觉得有点像策略模式,我觉得有那么点意味。。。。但还是有差别。 

      

      

      

  • 相关阅读:
    day15作业
    [原]iTop自定义修改相关时间字段的实现要点记录
    获取socket统计信息
    PG-跨库操作-postgres_fdw
    break跳出rewrite阶段,不会在匹配,进入输出阶段。 last 类似重新发起请求,所以会重新进行匹配。
    项目经验--把责任人定下来,流程理顺,工作开展会顺利很多
    异常排障
    docker stack的简单命令
    企业微信群机器人
    redis迁移方案 redis查看主从信息
  • 原文地址:https://www.cnblogs.com/z-qinfeng/p/12215988.html
Copyright © 2020-2023  润新知