一文读懂 Java 适配器设计模式

你有没有遇到过这样的场景:出国旅行,想给手机充电,却发现酒店的插座和自己的充电器插头不匹配?这时候,一个转换插头就能完美解决问题,它能把酒店插座的接口,转换成充电器能适配的接口。在 Java 编程世界里,也有类似的 “转换插头”,它就是适配器设计模式。接下来,就让我们一起揭开它的神秘面纱。​

一、什么是适配器设计模式​

适配器设计模式(Adapter Design Pattern)属于结构型设计模式,它的核心作用是将一个类的接口转换成客户希望的另一个接口 。就像上述提到的转换插头,在程序中,当我们有两个不兼容的接口,而又希望它们能协同工作时,适配器就派上用场了。通过适配器,原本无法合作的类可以顺利交互,让代码的扩展性和复用性大大提高。​

二、适配器设计模式的类型​

在 Java 中,适配器设计模式主要有两种类型:对象适配器和类适配器。

1.Java 中 220V 转换为 6V 的 类适配器 实现

类适配器是通过继承(Is - A)的方式来实现的。它继承被适配类,同时实现目标接口。不过,由于 Java 不支持多重继承,所以类适配器的使用场景相对较少。

⑴.中文实现思路

🧠 实现思路总结

⚙️ 中文代码实现

1.目标接口:手机充电器(6V)

/**
 * 手机充电器接口,定义6V低压输出标准
 */
public interface 手机充电器 {
    void 提供低压(); // 提供6V电压
}

2. 适配者:插座(220V)

/**
 * 插座类,提供220V高压电
 */
public class 插座 {
    public int 获取高压() {
        System.out.println("⚡ 插座提供 220V 高压电");
        return 220;
    }
}

3. 类适配器:电压转换器(继承 + 实现)

/**
 * 电压适配器类(类适配器):继承 插座 类并实现 手机充电器 接口
 */
public class 电压适配器 extends 插座 implements 手机充电器 {

    @Override
    public void 提供低压() {
        int 高压 = 获取高压(); // 调用继承自 插座 的方法
        int 低压 = 高压 / 37; // 模拟电压转换(220 / 37 ≈ 6)
        System.out.println("🔌 适配器将 220V 转换为 " + 低压 + "V 低压电");
    }
}

4. 客户端:手机充电

/**
 * 手机类,依赖手机充电器接口进行充电
 */
public class 手机 {
    public void 充电(手机充电器 充电器) {
        System.out.println("🔋 手机开始充电...");
        充电器.提供低压();
        System.out.println("✅ 充电完成!");
    }
}

5. 测试运行

public class 测试 {
    public static void main(String[] args) {
        // 创建适配器(类适配器)
        电压适配器 适配器 = new 电压适配器();

        // 创建手机
        手机 手机 = new 手机();

        // 使用适配器给手机充电
        手机.充电(适配器);
    }
}

运行结果:


⑵英文代码

角色定义
角色描述
目标接口(Target)MobileCharger,定义手机所需的 6V 输出接口。
适配者(Adaptee)Socket,提供 220V 高压电。
适配器(Adapter)VoltageAdapter,继承 Socket 并实现 MobileCharger,将 220V 转换为 6V。
⚙️ 代码实现

1. 目标接口:手机充电器(6V)

/**
 * 手机充电器接口,定义6V低压输出标准
 */
public interface MobileCharger {
    void deliverLowVoltage(); // 提供6V电压
}

2. 适配者:插座(220V)

/**
 * 插座类,提供220V高压电
 */
public class Socket {
    public int getHighVoltage() {
        System.out.println("⚡ 插座提供 220V 高压电");
        return 220;
    }
}

3. 类适配器:电压转换器(继承 + 实现)

/**
 * 电压适配器类(类适配器):继承 Socket 类并实现 MobileCharger 接口
 */
public class VoltageAdapter extends Socket implements MobileCharger {

    @Override
    public void deliverLowVoltage() {
        int highVoltage = getHighVoltage(); // 调用继承自 Socket 的方法
        int lowVoltage = highVoltage / 37; // 模拟电压转换
        System.out.println("🔌 适配器将 220V 转换为 " + lowVoltage + "V 低压电");
    }
}

4. 客户端:手机充电

/**
 * 手机类,依赖手机充电器接口进行充电
 */
public class Phone {
    public void charge(MobileCharger charger) {
        System.out.println("🔋 手机开始充电...");
        charger.deliverLowVoltage();
        System.out.println("✅ 充电完成!");
    }
}

5. 测试运行

public class Test {
    public static void main(String[] args) {
        // 创建适配器(类适配器)
        VoltageAdapter adapter = new VoltageAdapter();

        // 创建手机
        Phone phone = new Phone();

        // 使用适配器给手机充电
        phone.charge(adapter);
    }
}

运行结果

⚡ 插座提供 220V 高压电
🔌 适配器将 220V 转换为 6V 低压电
🔋 手机开始充电...
✅ 充电完成!

在 Java 中虽然不支持多继承,但只要适配者是一个类,而目标是一个接口,就可以通过 继承类并实现接口 的方式实现类适配器。

  • 在 Java 中,只要适配者是一个类,而目标是一个接口,就可以使用类适配器。
  • 如果你希望代码更灵活、适配器与适配者解耦,建议使用 对象适配器

2.Java 中 220V 转换为 6V 的 对象适配器 实现

⑴.Java 适配器设计模式:220V 电源给 6V 手机充电(中文代码版)

实现思路总结

中文代码实现

1. 目标接口:手机充电器(6V)

/**
 * 手机充电器接口,定义6V低压输出标准
 */
public interface 手机充电器 {
    void 提供低压(); // 提供6V电压
}

2. 适配者:插座(220V)

/**
 * 插座类,提供220V高压电
 */
public class 插座 {
    public int 获取高压() {
        System.out.println("⚡ 插座提供 220V 高压电");
        return 220;
    }
}

3. 适配器:电压转换器

/**
 * 电压适配器,将220V转换为6V
 */
public class 电压适配器 implements 手机充电器 {
    private 插座 插座;

    public 电压适配器(插座 插座) {
        this.插座 = 插座;
    }

    @Override
    public void 提供低压() {
        int 高压 = 插座.获取高压();
        int 低压 = 高压 / 37; // 简化模拟:220 / 37 ≈ 6V
        System.out.println("🔌 适配器将 220V 转换为 " + 低压 + "V 低压电");
    }
}

4. 客户端:手机充电

/**
 * 手机类,依赖手机充电器接口进行充电
 */
public class 手机 {
    public void 充电(手机充电器 充电器) {
        System.out.println("🔋 手机开始充电...");
        充电器.提供低压();
        System.out.println("✅ 充电完成!");
    }
}

5. 测试运行

public class 测试 {
    public static void main(String[] args) {
        插座 插座 = new 插座(); // 创建220V插座
        电压适配器 适配器 = new 电压适配器(插座); // 创建适配器
        手机 手机 = new 手机(); // 创建手机

        手机.充电(适配器); // 使用适配器给手机充电
    }
}

运行结果:

⑵英文代码

角色划分

适配器模式有三个核心角色:

角色描述
目标接口(Target)客户端期望的接口,这里是 MobileCharger,提供 6V 的低压输出。
适配者(Adaptee)需要被适配的接口或类,这里是 Socket,提供 220V 的高压输出。
适配器(Adapter)桥接目标与适配者的中间层,这里是 VoltageAdapter,将 220V 转换为 6V。
⚙️代码实现

1. 目标接口:手机充电器(6V)

// 手机充电器接口,提供 6V 低压输出
public interface MobileCharger {
    void deliverLowVoltage(); // 提供低压电
}

2. 适配者:插座(220V)

// 插座类,提供 220V 高压输出
public class Socket {
    public int getHighVoltage() {
        System.out.println("⚡ 插座提供 220V 高压电");
        return 220;
    }
}

3. 适配器:电压转换器

// 电压适配器,将 220V 转换为 6V
public class VoltageAdapter implements MobileCharger {
    private Socket socket;

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

    @Override
    public void deliverLowVoltage() {
        int highVoltage = socket.getHighVoltage();
        int lowVoltage = highVoltage / 37; // 简化模拟:220 / 37 ≈ 6
        System.out.println("🔌 适配器将 220V 转换为 " + lowVoltage + "V 低压电");
    }
}

4. 客户端:手机充电

// 手机类,依赖 MobileCharger 接口进行充电
public class Phone {
    public void charge(MobileCharger charger) {
        System.out.println("🔋 手机开始充电...");
        charger.deliverLowVoltage();
        System.out.println("✅ 充电完成!");
    }
}

测试运行

public class Client {
    public static void main(String[] args) {
        Socket socket = new Socket(); // 创建 220V 插座
        VoltageAdapter adapter = new VoltageAdapter(socket); // 创建适配器
        Phone phone = new Phone(); // 创建手机

        phone.charge(adapter); // 使用适配器给手机充电
    }
}

三、适配器用的比较多的地方

适配器设计模式更多的是代码层面上的变化,

比如我有一个接口,接口中有10个方法,如果我写一个类去实现这个接口,那必然要把接口中的所有方法都要重写,但实际情况呢!

是有可能我只用到了一个方法,其他的9个方法呢?我都不用去写代码,但是这个9个方法会写在我这个类中,觉得这9个方法有点碍事,那怎么办呢?

所以我们需要加一层中间层,这个中间层怎么加呢?重新写一个类去实现这个接口,然后去重写这个接口的所有方法,这时候你写的那个类呢?只要去继承这个类,然后去选择性的去重写某个方法,

通过这种方式,你就可以摆脱不相干的那9个方法,这个中间层就叫做适配器,这个也是适配器用的比较多的地方

适配器设计模式:解决接口方法冗余问题的代码示例

Java 接口的特性决定了实现类必须重写所有方法(除非该类是抽象类)。当接口方法很多而子类只需部分方法时,直接实现接口会导致大量冗余代码。此时使用 ** 接口适配器模式(缺省适配器)** 是最佳解决方案:

问题场景

当一个接口有多个方法(如10个),但具体实现类只需要用到其中1个方法时,强制实现所有方法会导致代码冗余
解决方案:通过适配器类(Adapter)提供默认空实现,让具体类只重写需要的方法。


1. 定义接口(包含10个方法)

public interface MyInterface {
    void m1();
    void m2();
    void m3();
    void m4();
    void m5();
    void m6();
    void m7();
    void m8();
    void m9();
    void m10();
}

2. 创建适配器类(中间层)

public abstract class Adapter implements MyInterface {
    @Override
    public void m1() {} // 默认空实现
    @Override
    public void m2() {}
    @Override
    public void m3() {}
    @Override
    public void m4() {}
    @Override
    public void m5() {}
    @Override
    public void m6() {}
    @Override
    public void m7() {}
    @Override
    public void m8() {}
    @Override
    public void m9() {}
    @Override
    public void m10() {}
}

3. 具体类:只重写需要的方法

public class ConcreteClass extends Adapter {
    @Override
    public void m1() {
        System.out.println("✅ Method m1 is implemented.");
    }
}

4. 客户端代码:使用适配器简化实现

public class Client {
    public static void main(String[] args) {
        MyInterface myInterface = new ConcreteClass();
        
        myInterface.m1(); // 输出: ✅ Method m1 is implemented.
        myInterface.m2(); // 无输出(由适配器提供空实现)
    }
}

四、适配器使用场景——功能合并

还有一种做法,我有一个别人写的类,这个类呢?不能去修改它,我又想把它融合在我的类中,

这种呢?叫做功能合并,就是把别人的功能合并到我的功能里面来——怎么办呢?比如A类中有一个m1方法,有一个B接口,接口中2个方法,一个叫m1,一个叫m2,我现在只想实现m2方法,m1方法呢?让他去调用a类的方法,a类呢?又不是我自己写的,又不能去修改别人的类,

这时候,你只需要写一个新的类去继承a类,实现b接口,然后在你的新类里面重写m2方法,这样b接口中的m1方法就自动转向了a类上的m1方法,这就是让原本没有办法合作在一起的,让它合作在一起。这种操作有点像多继承,其实在java之中,虽然不支持你类上面的多继承,但是它还是支持你继承一个类,实现多个接口的这种方式


以下是针对该场景的代码实现,通过继承不可修改的类 A 并实现接口 B,使新类 C 既能复用 A 的 m1 方法,又能实现 B 接口中的 m2 方法:


1.这个是类适配器

// 定义不可修改的类A,包含m1方法
class A {
    public void m1() {
        System.out.println("执行 A 类的 m1 方法");
    }
}

// 定义接口B,包含m1和m2方法
interface B {
    void m1();
    void m2();
}

// 新类C继承A并实现B
class C extends A implements B {
    // 无需显式重写m1方法,直接继承A的m1方法
    @Override
    public void m2() {
        System.out.println("执行 B 接口中 C 类实现的 m2 方法");
    }
}

// 测试类
public class Main {
    public static void main(String[] args) {
        C instance = new C();
        
        // 调用从A类继承的m1方法
        instance.m1(); 
        
        // 调用C类实现的m2方法
        instance.m2(); 
    }
}

代码解析:

  • 类 A:表示不可修改的外部类,包含方法 m1
  • 接口 B:定义了两个方法 m1 和 m2,要求实现类提供这两个方法的具体逻辑。
  • 类 C
    • 继承自类 A,从而直接复用 A 中的 m1 方法。
    • 实现接口 B,仅需显式重写 m2 方法(m1 方法由继承自 A 的实现来满足接口要求)。
  • 测试类 Main:创建 C 的实例,分别调用 m1 和 m2 方法,验证功能合并的效果。

这种方式利用了 Java 中 “单继承 + 多接口实现” 的特性,在不修改类 A 的前提下,将类 A 的功能与接口 B 的定义整合到新类 C 中,实现了 “功能合并”,使原本独立的类和接口得以协同工作。

为什么可以不重写m1方法

2.改用对象适配器

 定义类 A(原始类)

class A {
    public void m1() {
        System.out.println("A类的m1方法");
    }
}

定义接口 B(目标接口)

interface B {
    void mm1();
    void mm2();
}

创建对象适配器类

核心思路(手写):在适配器中重写mm1方法,mm1方法中使用a对象调用m1方法

class ObjectAdapter implements B {
    private final A a; // 组合类A的对象

    public ObjectAdapter() {
        this.a = new A();
    }

    @Override
    public void mm1() {
        a.m1(); // 调用类A的m1方法来实现接口B的mm1方法
    }

    @Override
    public void mm2() {
        System.out.println("实现B接口的mm2方法");
    }
}

 测试类(客户端调用)

public class Main {
    public static void main(String[] args) {
        B adapter = new ObjectAdapter();
        adapter.mm1(); // 输出:A类的m1方法
        adapter.mm2(); // 输出:实现B接口的mm2方法
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值