ningendo

适配器设计模式实战1

一.目的

  结合项目源码来深入理解适配器模式,本文通过mybatis3源码中的log适配来介绍适配器模式

二.介绍和作用

适配器模式(Adapter Pattern)

       在项目中一般可以将代码分为调用方和提供服务方,一般来说调用方希望使用一个统一的接口来调用服务,而服务方往往来自第三方库或者第三方代码,一般情况下很难做到和本项目的接口代码相兼容,为了解决这种矛盾,采用适配器模式的方式因运而生。

       适配器模式的作用:将第三方服务类的接口转换成本项目期望的接口来调用,主的目的是提供兼容性,让接口不匹配不能一起工作的类可以协同工作。也可以称其为包装器(Wrapper)

 

三.分类

  属于结构型模式的一种

  再细分的话可分为:类适配器模式、对象适配器模式、接口适配器模式

 

四.角色划分

 

 

Caller调用者类 : 定义客户端所需的接口,可以是抽象类或者接口,也可以是具体类

Adapter适配器 : 适配器可以调用服务方接口,作为一个转换器,对Adaptee和Caller进行适配,
适配器类是适配器模式的核心,在对象适配器中,

Adaptee 服务方类: 被适配的角色

 

 

五.代码实现

 

 

public class Adapter implements IAdapter {

    private Adaptee adaptee = new Adaptee();
    @Override
    public void callerMethod() {
        adaptee.serviceMetho();
    }
}

/**
 * 提供接口给调用方使用
 */
public interface IAdapter {
    void callerMethod();
}

/**
 * 服务方
 */
public class Adaptee {
    public void serviceMetho(){
        System.out.println("第三方服务");
    }
}

/**
 * 服务调用方
 */
public class Caller {
    public void call(){
        IAdapter adapter = new Adapter();
        adapter.callerMethod();
    }
}

public class App {
    public static void main(String[] args) {
        Caller caller = new Caller();
        caller.call();
    }
}

  

六.结合Mybatis3中的log适配来

 

 代码实现

public interface ILogAdapter {
    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);
}

  

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class JakartaCommonsLoggingImpl implements ILogAdapter { private final Log log; public JakartaCommonsLoggingImpl(String clazz) { log = LogFactory.getLog(clazz); } @Override public boolean isDebugEnabled() { return log.isDebugEnabled(); } @Override public boolean isTraceEnabled() { return log.isTraceEnabled(); } @Override public void error(String s, Throwable e) { log.error(s, e); } @Override public void error(String s) { log.error(s); } @Override public void debug(String s) { log.debug(s); } @Override public void trace(String s) { log.trace(s); } @Override public void warn(String s) { log.warn(s); } }

  

import java.util.logging.Level;
import java.util.logging.Logger;


public class Jdk14LoggingImpl implements ILogAdapter {

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

}

  

public class Log4jImpl implements ILogAdapter {

  private static final String FQCN = Log4jImpl.class.getName();

  private final Logger log;

  public Log4jImpl(String clazz) {
    log = Logger.getLogger(clazz);
  }

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

}

  

public class StdOutImpl implements ILogAdapter {

  public StdOutImpl(String clazz) {
    // Do Nothing
  }

  @Override
  public boolean isDebugEnabled() {
    return true;
  }

  @Override
  public boolean isTraceEnabled() {
    return true;
  }

  @Override
  public void error(String s, Throwable e) {
    System.err.println(s);
    e.printStackTrace(System.err);
  }

  @Override
  public void error(String s) {
    System.err.println(s);
  }

  @Override
  public void debug(String s) {
    System.out.println(s);
  }

  @Override
  public void trace(String s) {
    System.out.println(s);
  }

  @Override
  public void warn(String s) {
    System.out.println(s);
  }
}

  

public class LogFactory {
    private static Map<String,ILogAdapter> adapterMap = new HashMap<String,ILogAdapter>();

    static {
        adapterMap.put(JakartaCommonsLoggingImpl.class.getName(),new JakartaCommonsLoggingImpl(JakartaCommonsLoggingImpl.class.getName()));
        adapterMap.put(Jdk14LoggingImpl.class.getName(),new Jdk14LoggingImpl(Jdk14LoggingImpl.class.getName()));
        adapterMap.put(Log4jImpl.class.getName(),new Log4jImpl(Log4jImpl.class.getName()));
        adapterMap.put(NoLoggingImpl.class.getName(),new NoLoggingImpl(NoLoggingImpl.class.getName()));
        adapterMap.put(StdOutImpl.class.getName(),new StdOutImpl(StdOutImpl.class.getName()));
    }

    private LogFactory() {
        // disable construction
    }

    public static ILogAdapter getLog(Class<?> clazz) throws LogException {
        return getLog(clazz.getName());
    }

    public static ILogAdapter getLog(String logger) throws LogException {
        try {
            return adapterMap.get(logger);
        } catch (Throwable t) {
            throw new LogException("Error creating logger for logger " + logger + ".  Cause: " + t, t);
        }
    }
}

  

public class LogFactoryTest {

    @Test
    public void shouldUseCommonsLogging() throws LogException {
        ILogAdapter log = LogFactory.getLog(JakartaCommonsLoggingImpl.class);
        logSomething(log);
        assertEquals(log.getClass().getName(), JakartaCommonsLoggingImpl.class.getName());
    }

    @Test
    public void shouldUseJDK14Logging() throws LogException {
        ILogAdapter log = LogFactory.getLog(Jdk14LoggingImpl.class);
        logSomething(log);
        assertEquals(log.getClass().getName(), Jdk14LoggingImpl.class.getName());
    }

    @Test
    public void shouldUseLog4jImplLogging() throws LogException {
        ILogAdapter log = LogFactory.getLog(Log4jImpl.class);
        logSomething(log);
        assertEquals(log.getClass().getName(), Log4jImpl.class.getName());
    }

    @Test
    public void shouldStdOutImplImplLogging() throws LogException {
        ILogAdapter log = LogFactory.getLog(StdOutImpl.class);
        logSomething(log);
        assertEquals(log.getClass().getName(), StdOutImpl.class.getName());
    }

    private void logSomething(ILogAdapter log) {
        log.warn("Warning message.");
        log.debug("Debug message.");
        log.error("Error message.");
        log.error("Error with Exception.", new Exception("Test exception."));
    }

  

七.代码地址

上述代码地址: https://github.com/arxobject/mybatis_light/tree/master/logAdapter

mybatis3 源码地址 https://github.com/mybatis/mybatis-3

 

posted on 2020-08-21 18:45  Lunamonna  阅读(116)  评论(0编辑  收藏  举报

导航