一看就会-适配器模式(含代码讲解)

介绍

在软件开发中,我们经常会遇到各种各样的类库和组件,它们可能拥有不同的接口设计,导致无法直接协同工作。这时,适配器模式(Adapter Pattern)就派上用场了。

适配器模式 就像一个翻译官,它将一个类的接口转换成另一个接口,让原本不兼容的类可以互相配合。

核心思想:

  • 现有类(被适配者):已经存在,拥有我们想要的功能,但接口不符合我们的需求。
  • 目标接口:定义了我们期望的接口,是我们想要使用的接口。
  • 适配器:充当桥梁,将被适配者的接口转换为目标接口,让它们可以协同工作。

基础案例

你有一个手机充电器,它只能输出 5V 电压,而你的笔记本电脑需要 19V 电压才能正常工作。这时候,你需要一个适配器,将手机充电器的 5V 电压转换成 19V 电压,才能给笔记本电脑充电。

适配器模式 就如同这个转换器,它可以将一个接口(手机充电器)转换成另一个接口(笔记本电脑),让它们能够互相配合。

具体来说:

  • 手机充电器 代表着现有的功能,但它的输出电压不符合笔记本电脑的需求。
  • 笔记本电脑 代表着需要使用的设备,它需要 19V 电压才能正常工作。
  • 适配器 则是一个转换器,它将手机充电器的 5V 电压转换成 19V 电压,让笔记本电脑能够使用手机充电器供电。

代码示例:

// 目标接口
interface LaptopCharger {
    int output19V();
}

// 被适配者类
class PhoneCharger {
    public int output5V() {
        return 5;
    }
}

// 适配器类
class ChargerAdapter implements LaptopCharger {
    private PhoneCharger phoneCharger;

    public ChargerAdapter(PhoneCharger phoneCharger) {
        this.phoneCharger = phoneCharger;
    }

    @Override
    public int output19V() {
        int src = phoneCharger.output5V();
        System.out.println("原始电压:" + src + "V");
        int dst = src * 3.8; // 将 5V 电压转换成 19V 电压
        System.out.println("转换后电压:" + dst + "V");
        return dst;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        PhoneCharger phoneCharger = new PhoneCharger();
        LaptopCharger adapter = new ChargerAdapter(phoneCharger);
        int output19V = adapter.output19V();
        System.out.println("输出电压:" + output19V + "V");
    }
}

运行结果:

原始电压:5V
转换后电压:19V
输出电压:19V

看完这个例子,你已经对适配器模式有了不错的了解了。那么,如果我还想给台灯,显示器等电器充电呢,这个适配器又该如何设计?

进阶案例

新增了台灯,显示器

设计思路:

  1. 使用枚举类定义充电器类型,方便管理和维护。
  2. 使用接口定义充电器共有的方法,提高代码可扩展性。
  3. 使用适配器类将不同充电器类型的输出电压统一到一个方法中,简化客户端代码。

1. 定义接口:

interface Charger {
    String getName();
    int getVoltage();
}

2. 使用枚举类实现接口:

enum ChargerType implements Charger {
    PHONE("手机充电器", 5),
    LAPTOP("笔记本充电器", 19),
    LAMP("台灯充电器", 12),
    DISPLAY("显示器充电器", 24);

    private String name;
    private int voltage;

    ChargerType(String name, int voltage) {
        this.name = name;
        this.voltage = voltage;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getVoltage() {
        return voltage;
    }
}

3. 创建适配器类:

class ChargerAdapter {
    private PhoneCharger phoneCharger = new PhoneCharger();
    private LaptopCharger laptopCharger = new LaptopCharger();
    private LampCharger lampCharger = new LampCharger();
    private DisplayCharger displayCharger = new DisplayCharger();

    public int getVoltage(ChargerType chargerType) {
        switch (chargerType) {
            case PHONE:
                return phoneCharger.output5V();
            case LAPTOP:
                return laptopCharger.output19V();
            case LAMP:
                return lampCharger.output12V();
            case DISPLAY:
                return displayCharger.output24V();
            default:
                return 0;
        }
    }
}

4. 客户端代码:

public class Client {
    public static void main(String[] args) {
        ChargerAdapter adapter = new ChargerAdapter();
        System.out.println(ChargerType.PHONE.getName() + " 电压:" + adapter.getVoltage(ChargerType.PHONE));
        System.out.println(ChargerType.LAPTOP.getName() + " 电压:" + adapter.getVoltage(ChargerType.LAPTOP));
        System.out.println(ChargerType.LAMP.getName() + " 电压:" + adapter.getVoltage(ChargerType.LAMP));
        System.out.println(ChargerType.DISPLAY.getName() + " 电压:" + adapter.getVoltage(ChargerType.DISPLAY));
    }
}
手机充电器 电压:5
笔记本充电器 电压:19
台灯充电器 电压:12
显示器充电器 电压:24

代码讲解:

  1. 接口定义:

    • Charger 接口定义了所有充电器类型共有的方法 getName() 和 getVoltage()
  2. 枚举类实现接口:

    • ChargerType 枚举类实现了 Charger 接口,并定义了四种充电器类型:PHONELAPTOPLAMPDISPLAY
    • 每个枚举值包含 name 和 voltage 属性,分别表示充电器名称和电压。
    • getName() 和 getVoltage() 方法分别返回枚举值的名称和电压。
  3. 适配器类:

    • ChargerAdapter 类充当适配器,它包含了四个私有属性,分别对应四种充电器类型。
    • getVoltage() 方法接收一个 ChargerType 枚举值作为参数,根据枚举值类型调用对应充电器的输出电压方法。
    • 这里使用了 switch 语句来判断枚举值类型,并调用对应充电器的输出电压方法。

能看到这里你已经基本掌握了开发中适配器模式的使用,还有一个问题,就是后续增加了新的充电器怎么办?要回去动Switch语句吗?怎么优化?

代码优化

使用 switch 语句虽然简单,但如果以后新增了充电器类型,就需要修改 ChargerAdapter 的代码,这违背了“开闭原则”。

1. 使用 Map

可以使用 Map 来存储充电器类型和对应充电器对象的映射关系

class ChargerAdapter {
    private Map<ChargerType, DeviceCharger> chargerMap = new HashMap<>();

    public ChargerAdapter() {
        chargerMap.put(ChargerType.PHONE, new PhoneCharger());
        chargerMap.put(ChargerType.LAPTOP, new LaptopCharger());
        chargerMap.put(ChargerType.LAMP, new LampCharger());
        chargerMap.put(ChargerType.DISPLAY, new DisplayCharger());
    }

    public int getVoltage(ChargerType chargerType) {
        DeviceCharger charger = chargerMap.get(chargerType);
        if (charger != null) {
            return charger.outputVoltage();
        } else {
            return 0;
        }
    }
}

这样,当新增充电器类型时,我们只需要在 chargerMap 中添加新的映射关系即可,无需修改 ChargerAdapter 的代码。

2. 使用反射:

我们可以使用反射机制来动态创建充电器对象。

class ChargerAdapter {
    public int getVoltage(ChargerType chargerType) {
        try {
            Class<?> chargerClass = Class.forName(chargerType.name() + "Charger");
            DeviceCharger charger = (DeviceCharger) chargerClass.newInstance();
            return charger.outputVoltage();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
            return 0;
        }
    }
}

这样,当新增充电器类型时,我们只需要创建新的充电器类,并确保类名符合 ChargerType 枚举值的命名规范即可,无需修改 ChargerAdapter 的代码。

都看到这了,求大佬赏个赞赞

  • 21
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一种接口。这种模式通常用于使现有的类能够与其他类一起工作,而不需要修改它们的源代码。 下面是一个使用适配器模式的示例代码: ```python # 定义一个需要被适配的接口 class Adaptee: def specific_request(self): return "specific request" # 定义一个客户端所期望的接口 class Target: def request(self): return "default request" # 定义一个适配器,将 Adaptee 转换成 Target class Adapter(Target): def __init__(self, adaptee): self.adaptee = adaptee def request(self): return self.adaptee.specific_request() # 客户端代码 def client_code(target): print(target.request()) if __name__ == "__main__": adaptee = Adaptee() adapter = Adapter(adaptee) client_code(adapter) ``` 在上面的代码中,`Adaptee` 是需要被适配的类,它有一个 `specific_request` 方法。`Target` 是客户端所期望的接口,它有一个 `request` 方法。`Adapter` 是适配器类,它将 `Adaptee` 转换成 `Target`,并实现了 `Target` 的 `request` 方法。客户端代码可以接受 `Target` 类型的对象作为参数,因此我们创建了一个 `Adapter` 对象并将其传递给客户端代码。 当客户端代码调用 `adapter.request()` 时,由于 `Adapter` 继承了 `Target`,因此它的 `request` 方法被调用。`Adapter` 的 `request` 方法调用 `Adaptee` 的 `specific_request` 方法,从而实现了 `Adaptee` 到 `Target` 的适配。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值