适配器模式(Adapter Pattern)

适配器模式(Adapter Pattern)

适配器模式是一种结构型设计模式,它通过将一个类的接口转换成客户端期望的另一个接口,使得原本接口不兼容的类可以协同工作。适配器模式的核心是接口转换,它充当两个不兼容接口之间的桥梁。

模式结构

  1. 目标接口(Target)
    定义客户端需要的接口方法。
  2. 适配者类(Adaptee)
    现有的类,其接口与客户端需求不兼容,需要被适配。
  3. 适配器类(Adapter)
    实现目标接口,并通过继承或组合的方式调用适配者类的方法,完成接口转换。

适配器模式有两种实现方式:

  • 类适配器:通过继承适配者类实现目标接口。
  • 对象适配器:通过组合适配者类的实例实现目标接口。

代码示例

1. 目标接口(Target)

// 目标接口:定义客户端需要的电压获取方法
interface SocketAdapter {
    Volt get120Volt();
    Volt get12Volt();
    Volt get3Volt();
}

2. 适配者类(Adaptee)

// 适配者类:现有插座类,仅支持120V电压
class Socket {
    public Volt getVolt() {
        return new Volt(120);
    }
}

3. 类适配器(Class Adapter)

// 类适配器:通过继承适配者类实现目标接口
class SocketClassAdapterImpl extends Socket implements SocketAdapter {
    @Override
    public Volt get120Volt() {
        return super.getVolt();
    }

    @Override
    public Volt get12Volt() {
        return convertVolt(super.getVolt(), 10);
    }

    @Override
    public Volt get3Volt() {
        return convertVolt(super.getVolt(), 40);
    }

    private Volt convertVolt(Volt volt, int divisor) {
        return new Volt(volt.getVolts() / divisor);
    }
}

4. 对象适配器(Object Adapter)

// 对象适配器:通过组合适配者类的实例实现目标接口
class SocketObjectAdapterImpl implements SocketAdapter {
    private final Socket socket;

    public SocketObjectAdapterImpl(Socket socket) {
        this.socket = socket;
    }

    @Override
    public Volt get120Volt() {
        return socket.getVolt();
    }

    @Override
    public Volt get12Volt() {
        return convertVolt(socket.getVolt(), 10);
    }

    @Override
    public Volt get3Volt() {
        return convertVolt(socket.getVolt(), 40);
    }

    private Volt convertVolt(Volt volt, int divisor) {
        return new Volt(volt.getVolts() / divisor);
    }
}

5. 调用示例

public class AdapterPattern {
    public static void main(String[] args) {
        // 使用类适配器
        SocketAdapter classAdapter = new SocketClassAdapterImpl();
        System.out.println("类适配器输出:");
        System.out.println("3V电压:" + classAdapter.get3Volt().getVolts());
        System.out.println("12V电压:" + classAdapter.get12Volt().getVolts());

        // 使用对象适配器
        SocketAdapter objectAdapter = new SocketObjectAdapterImpl(new Socket());
        System.out.println("\n对象适配器输出:");
        System.out.println("3V电压:" + objectAdapter.get3Volt().getVolts());
        System.out.println("12V电压:" + objectAdapter.get12Volt().getVolts());
    }
}

输出结果

类适配器输出:
3V电压:3
12V电压:12

对象适配器输出:
3V电压:3
12V电压:12

应用场景

  1. 集成第三方库或旧系统
    当需要复用已有的类,但其接口与当前系统不兼容时,可以使用适配器模式。
  2. 统一多个类的接口
    当多个类提供类似功能但接口不同时,适配器模式可以统一接口调用方式。
  3. 接口版本升级
    在新接口需要兼容旧接口时,适配器可以作为中间层平滑过渡。

在Java中的应用

  • java.io.InputStreamReaderOutputStreamWriter
    这两个类将字节流(InputStream/OutputStream)适配为字符流(Reader/Writer)。
  • 集合框架
    java.util.Collections.list(Enumeration) 方法将旧的 Enumeration 接口适配为 List 接口。
  • GUI事件处理
    Java Swing中的事件监听器适配器类(如WindowAdapter)提供默认实现,简化事件处理。

优缺点

优点

  1. 解耦
    客户端代码与适配者类解耦,只需依赖目标接口。
  2. 复用性
    可以复用现有的类,无需修改其代码。
  3. 灵活性
    对象适配器支持动态组合,适用于需要适配多个类的场景。

缺点

  1. 复杂性增加
    引入适配器类会增加代码结构的复杂度。
  2. 过度适配
    如果滥用适配器模式,可能导致系统层次过多,难以维护。

总结

适配器模式通过接口转换,解决了不兼容类之间的协作问题。它适用于集成第三方库、复用旧代码或统一多个接口的场景。类适配器通过继承实现,简单但受限于单继承;对象适配器通过组合实现,更灵活且符合合成复用原则。在Java中,适配器模式广泛应用于IO流、集合框架和GUI开发中,是解决接口兼容性问题的经典方案。