适配器设计模式实战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
浙公网安备 33010602011771号