网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|
原有系统已经从各个供应商中获取到航班数据、格式为 XML、并且将该数据传输给一个智能分析系统中做统计分析。最近业务改动、对接了一个新的智能分析系统、但是对方的输入格式为 Json、这个时候我们该怎么办?
我们可以创建一个适配器、该适配器实现原来的智能分析接口、在适配器里面做 XML 到 JSON 的转换、然后再真正的调用新的智能分析系统。对于应用系统而言、甚至可以不改动代码。
网络异常,图片无法展示
|
Mybatis 的适配器模式
现存主流的日志框架有 Logback、Log4j、Log4j2 等、但是大部分都是先使用 SLF4J 作为门面、通过其底层适配到具体的日志框架中。
Mybatis 中定义了自己的内部 Log 接口、然后通过适配器模式适配应用真实使用的日志框架
package org.apache.ibatis.logging; 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); } 复制代码
Log
接口就相当于 Client Interface
Jdk14LoggingImpl
这个就相当于适配器
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); } } 复制代码
而java.util.logging.Logger
则相当于被适配的服务。
网络异常,图片无法展示
|
Mybatis 这种场景不像上面所说的供应商数据分析那种场景那么明显、因为好像 Mybatis 在项目前期就可以选择一款日志框架一样、但是并不是、它更想使用应用本身的日志框架。
或者这么说、Mybatis 自身就有了一套日志接口、面对市面上多种多样的日志框架、Mybatis 自身的接口与这些框架不兼容、而 Mybatis 更加不可能改动这些已经存在的第三方日志框架、所以它只能一个个去适配这些可能被应用使用到的框架。换这种角度、就非常适合。
网络异常,图片无法展示
|
可以看到 Mybatis 为了各种日志框架而做的各种适配器
再看看 Mybatis 如何选择出合适的适配器的
// LogFactory static { tryImplementation(LogFactory::useSlf4jLogging); tryImplementation(LogFactory::useCommonsLogging); tryImplementation(LogFactory::useLog4J2Logging); tryImplementation(LogFactory::useLog4JLogging); tryImplementation(LogFactory::useJdkLogging); tryImplementation(LogFactory::useNoLogging); } public static synchronized void useSlf4jLogging() { setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class); } 复制代码
网络异常,图片无法展示
|
尝试去创建每种适配器、如果成功则说明了应用有使用到该日志框架、看到优先的是日志门面 LF4J
优点
- 单一职责原则、可以将接口转换和数据转换从原有的逻辑中抽离、每个日志适配器类中、都是各个日志框架具体的调用、当然、日志的接口都是比较简单、基本都是转发接口、当然也存在其他复杂的情况
- 开闭原则、Mybatis 只需要使用自己本来自定义的 Logger 接口即可、不需要知道具体日志框架。当然在上面的例子中甚至使用了静态工厂的方法、使应用甚至都不知道具体的适配器类或者接口的具体实现。即使以后市面上又出现另一个流行的日志框架、对于 Mybatis 来说、只是需要增加一个适配器类。(修改静态工厂这个是另外的话题、跟适配器模式没啥关系)
缺点
- 很明显、代码复杂度高了、单纯适配器都好几个了。在这里如果直接使用某一个确定的日志框架、那么就不会存在这些适配器类了、但是这样的话、应用如果使用不同的框架、那么应用就需要配置维护两个日志框架了(当然可以使用 SL4J 再桥接过去)、这样子显然是非常不友好的。
与其他设计模式的关系
- 桥接模式、桥接模式通常更加适用于开发前期设计、使你能够将程序的各个部分独立开来以便开发。适配器模式通常在已有的程序中使用、让相互不兼容的类能很好的合作
- 装饰模式能在不改变对象接口的前提下强化对象的功能、并且可以递归组合、而适配器模式可以对接口进行修改(如果是新增一个新的功能、这个功能也是需要适配各种服务)、适配器模式则不能递归组合
- 适配器能为被封装对象提供不同的接口、代理模式能为对象提供相同的接口、装饰则能为对象提供加强接口。