第一、适配器模式定义
适配器指的的是将一个系统的接口转换为另外一种形式,由原来的不能直接调用的接口变得可以调用。
适配器适用于以下几种业务场景:
1、已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。
2、适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案。有点亡羊补牢的感觉。
生活中也非常的应用场景,例如电源插转换头、手机充电转换头、显示器转接头。
3、新老版本的接口的兼容
4、Mybatis多种日志框架的整合
第二、适配器的角色划分
适配器模式涉及3个角色:
源(Adaptee):需要被适配的对象或类型, 旧版本或者苹果手机插口
适配器(Adapter):连接目标和源的中间对象,相当于插头转换器,新版本与老版本能够实现兼容
目标(Target):期待得到的目标, 新版本或者圆子头耳机
适配器模式包括3种形式:类适配器模式、对象适配器模式、接口适配器模式(或又称作缺省适配器模式)。
第三、适配器快速入门案例
比如早期的时候V1版本订单接口的入参为Map类型,随着业务的更新和迭代在V2版本的时候该订单接口的入参需要支持List的类型? 请问不改变的该接口代码的情况下,如何实现支持List类型。
/**
* 实现类
*/
public class ListEx {
public static void froOrderMap(Map map) {
for (int i = 0; i < map.size(); i++) {
// 使用I作为MapKey获取数据
Integer value = Integer.valueOf(map.get(i).toString());
System.out.println("value:" + value);
}
}
}
/**
* list适配器
*/
public class ListAdapter extends HashMap {
private List<Integer> list;
public ListAdapter(List<Integer> list){
this.list = list;
}
@Override
public Object get(Object key) {
return list.get(Integer.valueOf(key.toString()));
}
@Override
public int size() {
return list.size();
}
public void add(Object key){
list.add(Integer.valueOf(key.toString()));
}
}
/**
* 测试类
*/
public class Test001 {
public static void main(String[] args) {
ListAdapter list = new ListAdapter(new ArrayList<Integer>());
list.add(1);
list.add(2);
list.add(3);
list.add(4);
ListEx.froOrderMap(list);
}
}
第四、使用适配器模式实现日志收集
比如设计一个日志收集系统,可能会考虑文件写入、也可能考虑写入MQ、也可能考虑写入数据库等。
/**
* 写入文件
*/
public interface LogWriteFileService {
public void writerFile();
}
/*
实现类
*/
public class LogWriteFileServiceImpl implements LogWriteFileService {
@Override
public void writerFile() {
System.out.println("写入文件");
}
}
/**
* 写入数据库
*/
public interface LogWriterDBService {
public void writerDB();
}
/**
* 适配器
*/
public class LogAdapter extends LogWriteFileServiceImpl implements LogWriterDBService {
@Override
public void writerDB() {
System.out.println("将数据写入数据库");
//将数据写入文件
this.writerFile();
}
}
/**
* 测试类
*/
public class Test002 {
public static void main(String[] args) {
LogAdapter logAdapter = new LogAdapter();
logAdapter.writerDB();
}
}
第五、适配器的优缺点
优点:
1、能提高类的透明性和复用,现有的类复用但不需要改变。
2、目标类和适配器类解耦,提高程序的扩展性。
3、在很多业务场景中符合开闭原则。
缺点:
1、适配器编写过程需要全面考虑,可能会增加系统的复杂性。
2、增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
第六、mybatis日志收集
Java开发中经常用到的日志框架有很多,Log4j、Log4j2、slf4j等等,Mybatis定义了一套统一的日志接口供上层使用,并为上述常用的日志框架提供了相应的适配器
在Mybatis的日志模块中就是使用了适配器模式。Mybatis内部在使用日志模块时,使用了其内部接口 org.apache.ibatis.logging.Log,但是常用的日志框架的对外接口各不相同,Mybatis为了复用和集成这些第三方日志组件,在其日志模块中,提供了多种Adapter,将这些第三方日志组件对外接口适配成org.apache.ibatis.logging.Log,这样Myabtis 就可以通过Log接口调用第三方日志了
源码分析