适配器模式
Adapter — 把不兼容的接口转换成客户端期望的接口
一句话理解
在两个不兼容的接口之间加一个转换器,让它们能协同工作。就像电源适配器把 220V 转成 5V 一样。
解决什么问题
- 想复用一个已有的类,但它的接口和你需要的不一致
- 对接第三方库/旧系统,接口不匹配
- 不想(或不能)修改已有代码
怎么写
场景:系统期望的是 Target 接口,但已有的类是 Adaptee,接口不匹配。
// 客户端期望的接口
public interface Target {
void request();
}
// 已有的类,接口不兼容
public class Adaptee {
public void specificRequest() {
System.out.println("Adaptee 的特殊方法");
}
}
// 适配器:实现目标接口,内部委托给 Adaptee
public class Adapter implements Target {
private final Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 把调用转发给 Adaptee
adaptee.specificRequest();
}
}// 使用:客户端只面向 Target 接口
Target target = new Adapter(new Adaptee());
target.request(); // 内部调用了 Adaptee.specificRequest()实际例子:对接多种支付
// 统一支付接口
public interface PayService {
void pay(double amount);
}
// 支付宝 SDK(第三方,接口不同)
public class AlipaySDK {
public void sendPayment(double money) { /* ... */ }
}
// 适配器
public class AlipayAdapter implements PayService {
private final AlipaySDK sdk = new AlipaySDK();
@Override
public void pay(double amount) {
sdk.sendPayment(amount); // 转换调用
}
}前端中的适配器
// 后端返回的数据格式和前端组件期望的不一致
// 适配器函数做转换
function adaptUserData(apiData: ApiUser): ComponentUser {
return {
id: apiData.user_id, // user_id -> id
fullName: apiData.full_name, // full_name -> fullName
avatar: apiData.avatar_url, // avatar_url -> avatar
}
}使用场景
- Java I/O:
InputStreamReader把字节流适配成字符流 - Spring MVC:
HandlerAdapter把不同类型的 Handler 适配到统一的处理流程 - 前端数据转换层(API 响应 → 组件 Props)
- 旧系统改造中的接口兼容层