适配器模式 (Adapter Pattern)
模式定义
适配器模式是一种结构型设计模式,它将一个类的接口转换成客户希望的另一个接口,使得原本接口不兼容的类可以一起工作。
类适配器 vs 对象适配器
| 特性 | 类适配器 | 对象适配器 |
|---|---|---|
| 实现方式 | 继承 | 组合 |
| 适配目标 | 单个类 | 多个类 |
| 灵活性 | 较低 | 较高 |
| 推荐程度 | 不推荐 | 推荐 |
实现示例:日志框架适配
目标接口
java
// 期望的日志接口
public interface Logger {
void debug(String message);
void info(String message);
void warn(String message);
void error(String message);
}已有类(被适配者)
java
// 旧的日志类 - 接口不兼容
public class LegacyLog {
public void logDebug(String msg) {
System.out.println("[LEGACY-DEBUG] " + msg);
}
public void logInfo(String msg) {
System.out.println("[LEGACY-INFO] " + msg);
}
public void logWarning(String msg) {
System.out.println("[LEGACY-WARN] " + msg);
}
public void logError(String msg) {
System.out.println("[LEGACY-ERROR] " + msg);
}
}
// 第三方日志库 - 另一个不兼容的接口
public class ThirdPartyLogger {
public void writeLog(String level, String message) {
System.out.println("[THIRD-PARTY][" + level + "] " + message);
}
}对象适配器(推荐)
java
// 适配旧日志类
public class LegacyLogAdapter implements Logger {
private final LegacyLog legacyLog;
// 通过组合方式持有被适配对象
public LegacyLogAdapter(LegacyLog legacyLog) {
this.legacyLog = legacyLog;
}
@Override
public void debug(String message) {
legacyLog.logDebug(message);
}
@Override
public void info(String message) {
legacyLog.logInfo(message);
}
@Override
public void warn(String message) {
legacyLog.logWarning(message);
}
@Override
public void error(String message) {
legacyLog.logError(message);
}
}
// 适配第三方日志库
public class ThirdPartyLoggerAdapter implements Logger {
private final ThirdPartyLogger thirdPartyLogger;
public ThirdPartyLoggerAdapter(ThirdPartyLogger thirdPartyLogger) {
this.thirdPartyLogger = thirdPartyLogger;
}
@Override
public void debug(String message) {
thirdPartyLogger.writeLog("DEBUG", message);
}
@Override
public void info(String message) {
thirdPartyLogger.writeLog("INFO", message);
}
@Override
public void warn(String message) {
thirdPartyLogger.writeLog("WARN", message);
}
@Override
public void error(String message) {
thirdPartyLogger.writeLog("ERROR", message);
}
}类适配器(继承方式)
java
// 通过继承方式适配
public class LegacyLogClassAdapter extends LegacyLog implements Logger {
@Override
public void debug(String message) {
logDebug(message); // 调用父类方法
}
@Override
public void info(String message) {
logInfo(message);
}
@Override
public void warn(String message) {
logWarning(message);
}
@Override
public void error(String message) {
logError(message);
}
}使用示例
java
public class AdapterDemo {
public static void main(String[] args) {
// 使用旧日志适配器
Logger logger1 = new LegacyLogAdapter(new LegacyLog());
logger1.debug("这是调试信息");
logger1.info("这是普通信息");
logger1.warn("这是警告信息");
logger1.error("这是错误信息");
System.out.println("---");
// 使用第三方日志适配器
Logger logger2 = new ThirdPartyLoggerAdapter(new ThirdPartyLogger());
logger2.debug("这是调试信息");
logger2.info("这是普通信息");
logger2.warn("这是警告信息");
logger2.error("这是错误信息");
}
}双向适配器
java
// 双向适配器,可以同时适配两个方向
public class BidirectionalAdapter implements LegacyLog, ThirdPartyLogger {
private final LegacyLog legacyLog;
private final ThirdPartyLogger thirdPartyLogger;
public BidirectionalAdapter(LegacyLog legacyLog, ThirdPartyLogger thirdPartyLogger) {
this.legacyLog = legacyLog;
this.thirdPartyLogger = thirdPartyLogger;
}
// LegacyLog 接口的方法
@Override
public void logDebug(String msg) {
thirdPartyLogger.writeLog("DEBUG", msg);
}
@Override
public void logInfo(String msg) {
thirdPartyLogger.writeLog("INFO", msg);
}
@Override
public void logWarning(String msg) {
thirdPartyLogger.writeLog("WARN", msg);
}
@Override
public void logError(String msg) {
thirdPartyLogger.writeLog("ERROR", msg);
}
// ThirdPartyLogger 接口的方法
@Override
public void writeLog(String level, String message) {
switch (level) {
case "DEBUG": legacyLog.logDebug(message); break;
case "INFO": legacyLog.logInfo(message); break;
case "WARN": legacyLog.logWarning(message); break;
case "ERROR": legacyLog.logError(message); break;
}
}
}JDK 中的适配器模式
InputStreamReader / OutputStreamWriter
java
// InputStreamReader: 适配器,将 InputStream 适配为 Reader
Reader reader = new InputStreamReader(System.in, "UTF-8");
// OutputStreamWriter: 适配器,将 OutputStream 适配为 Writer
Writer writer = new OutputStreamWriter(System.out, "UTF-8");实际应用
- 日志框架: 统一不同日志框架的接口
- 数据格式转换: XML 转 JSON、CSV 转 Bean
- API 版本兼容: 旧 API 适配新接口
- 第三方库集成: 封装不兼容的接口
优缺点
优点:
- 符合开闭原则,无需修改现有代码
- 提高代码复用性
- 增强灵活性和可扩展性
缺点:
- 增加系统复杂度
- 间接层过多可能影响性能