目录
一、适配器模式定义
HandlerAdapter 在 Spring MVC 中使用了适配器模式
适配器模式, 也叫包装器模式。将一个类的接口,转换成客户期望的另一个接口, 适配器让原本接口不兼容的类可以合作无间。
简单来说就是目标类不能直接使用,通过一个新类进行包装一下, 适配调用方法使用, 把两个不兼容的接口通过一定的方式使之兼容。
比如下面两个接口,本身是不兼容的(参数类型不一样, 参数个数不一样等等)
通过适配器,使之兼容:
二、适配器模式角色
- Target: 目标接口 (可以是抽象类或接口),客户希望直接用的接口;
- Adaptee: 适配者, 但是与Target不兼容;
- Adapter: 适配器类, 此模式的核心。 通过继承或者引用适配者的对象, 把适配者转为目标接口;
- client: 需要使用适配器的对象。
三、适配器模式的实现
slf4j 就使用了适配器模式, slf4j提供了一系列打印日志的api,底层调用的是log4j 或者 logback 来打日志,作为调用者,只需要调用slf4j的api就行。
java
/**
* slf4j接口
*/
interface Slf4jApi{
void log(String message);
}
/**
* log4j 接口
*/
class Log4j{
void log4jLog(String message){
System.out.println("Log4j打印:"+message);
}
}
/**
* slf4j和log4j适配器
*/
class Slf4jLog4JAdapter implements Slf4jApi{
private Log4j log4j;
public Slf4jLog4JAdapter(Log4j log4j) {
this.log4j = log4j;
}
@Override
public void log(String message) {
log4j.log4jLog(message);
}
}
/**
* 客户端调用
*/
public class Slf4jDemo {
public static void main(String[] args) {
Slf4jApi slf4jApi = new Slf4jLog4JAdapter(new Log4j());
slf4jApi.log("使⽤slf4j打印⽇志");
}
}
可以看出不需要改变log4j的api,只需要通过适配器转换下, 就可以更换日志框架,保障系统的平稳运行。
适配器模式的实现并不在slf4j-core中(只定义了Logger),具体实现是在针对log4j的桥接器项目slf4j-log4j12中。
四、适配器模式应用场景
一般来说,适配器模式可以看作一种"补偿模式",用来补救设计上的缺陷。应用这种模式算是"无奈之举", 如果在设计初期能协调规避接口不兼容的问题, 就不需要使用适配器模式了。
所以适配器模式更多的应用场景主要是对正在运行的代码进行改造, 并且希望可以复用原有代码实现新的功能。比如版本升级等。