小易说IT 小易说IT

Java 适配器模式(Adapter)示例代码

适配器模式分为类适配器(继承实现)对象适配器(组合实现,实际项目最常用),还有接口适配器(缺省适配器)。

核心作用:将一个类的接口,转换成客户期望的另一个接口,让原本接口不兼容的类可以一起工作。

1、对象适配器(推荐,组合方式,Java 优先使用,规避单继承限制)

场景示例:现有 220V家用交流电,目标需要输出 5V 给手机充电,适配器充当充电器。

/**
 * 被适配者:家用220V交流电
 */
public class Ac220V {
    public int output220V() {
        return 220;
    }
}

/**
 * 目标接口:手机需要5V电压
 */
public interface Target5V {
    int output5V();
}

/**
 * 对象适配器:充电器,组合持有被适配对象
 */
public class VoltageAdapter implements Target5V {

    // 组合:持有被适配对象,不使用继承
    private final Ac220V ac220V;

    public VoltageAdapter(Ac220V ac220V) {
        this.ac220V = ac220V;
    }

    @Override
    public int output5V() {
        int src = ac220V.output220V();
        System.out.println("适配器转换:输入电压=" + src + "V");
        int dst = src / 44; // 220 /44 =5
        System.out.println("适配器输出:" + dst + "V");
        return dst;
    }
}

/**
 * 客户端:手机
 */
public class Phone {
    public void charge(Target5V target5V){
        int v = target5V.output5V();
        System.out.println("手机使用 "+v+"V 充电");
    }
}

// 测试主类
class TestMain {
    public static void main(String[] args) {
        Ac220V ac220V = new Ac220V();
        Target5V adapter = new VoltageAdapter(ac220V);
        Phone phone = new Phone();
        phone.charge(adapter);
    }
}

输出:

适配器转换:输入电压=220V
适配器输出:5V
手机使用 5V 充电

2、类适配器(继承实现,Java 受单继承限制,实际很少用)

缺点:Java 只能单继承,如果被适配类已经继承其他类,就无法使用。

// 被适配者
class Ac220V2 {
    public int output220V(){
        return 220;
    }
}

// 目标接口
interface Target5V2 {
    int output5V();
}

/**
 * 类适配器:直接继承被适配类,实现目标接口
 */
class VoltageClassAdapter extends Ac220V2 implements Target5V2{
    @Override
    public int output5V() {
        int src = output220V();
        return src / 44;
    }
}

// 测试
class ClassAdapterTest{
    public static void main(String[] args) {
        Target5V2 adapter = new VoltageClassAdapter();
        System.out.println(adapter.output5V());
    }
}

3、接口适配器(缺省适配器模式)

当不想实现接口中全部方法,写一个抽象适配器空实现所有接口方法,子类只重写需要的方法。

// 有很多抽象方法的接口
interface ManyMethodInterface {
    void func1();
    void func2();
    void func3();
}

/**
 * 缺省适配器,空实现全部接口方法
 */
abstract class AbsAdapter implements ManyMethodInterface{
    @Override
    public void func1() {}
    @Override
    public void func2() {}
    @Override
    public void func3() {}
}

// 业务子类,只重写自己需要的方法
class BusinessDemo extends AbsAdapter{
    @Override
    public void func2() {
        System.out.println("只实现func2业务逻辑");
    }
}

class DefaultAdapterTest{
    public static void main(String[] args) {
        ManyMethodInterface demo = new BusinessDemo();
        demo.func2();
    }
}

4、JDK 中适配器典型例子

java.util.Arrays#asList()SpringMVC HandlerAdapter(处理器适配器) SpringMVC HandlerAdapter 伪代码示意:

// 目标接口
public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(Object handler);
}

// 多种适配器适配不同Controller实现
class HttpRequestHandlerAdapter implements HandlerAdapter{...}
class SimpleControllerHandlerAdapter implements HandlerAdapter{...}

总结

  1. 对象适配器(组合)优先使用,解耦,不受 Java 单继承约束;

  2. 类适配器依靠继承,耦合高,业务尽量避免;

  3. 接口适配器适合接口方法多,只想重写部分方法场景。


本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://www.yijunzhao.cc/archives/java-adapter-pattern-example-code

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/