Skip to content

适配器模式 (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 适配新接口
  • 第三方库集成: 封装不兼容的接口

优缺点 ​

优点:

  • 符合开闭原则,无需修改现有代码
  • 提高代码复用性
  • 增强灵活性和可扩展性

缺点:

  • 增加系统复杂度
  • 间接层过多可能影响性能