目录
🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解代理模式请看: (六)趣学设计模式 之 代理模式!
一、 啥是适配器模式?
想象一下,你买了一个新的电器 💡,但是插头和家里的插座不匹配 😫,怎么办? 这时候就需要一个插座转换器 🔌,把电器的插头转换成家里的插座可以使用的类型 💡。
适配器模式,就是用来解决接口不兼容的问题! 它可以将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 🤝。
简单来说,就是把不兼容的接口转换成兼容的接口!
- 你想使用一个类,但是它的接口和你需要的接口不一样: 就像你想用一个旧的类库,但是它的接口和你的代码不兼容 😫!
- 你想让两个接口不兼容的类一起工作: 就像你想让一个美国的插头和一个中国的插座一起工作 🔌!
- 你想重用一些现有的类,但是它们的接口不符合你的要求: 就像你想用一个旧的算法,但是它的输入输出格式和你的代码不兼容 😫!
二、 为什么要用适配器模式?
用适配器模式,好处多多 👍:
- 提高类的复用性: 可以将一些现有的类适配成新的接口,方便重用 ♻️!
- 提高系统的灵活性: 可以动态地选择不同的适配器,使得系统更加灵活 🤸!
- 符合开闭原则: 可以在不修改现有代码的情况下,增加新的适配器,扩展功能 🆕!
- 解耦: 将客户端和目标类解耦,降低系统的耦合度 🔗!
三、 适配器模式的实现方式
适配器模式主要分为三种:
- 类适配器模式: 通过继承来实现适配,就像继承了插座的类 👨👩👧👦!
- 对象适配器模式: 通过组合来实现适配,就像用一个插座转换器 🔌!
- 接口适配器模式: 通过实现一个抽象类来实现适配,就像万能插座 🗜️!
1. 类适配器模式(继承插座 👨👩👧👦)
类适配器模式,通过继承来实现适配,就像继承了插座的类,拥有了插座的功能 🔌!
案例:电压适配器(经典案例 ⚡)
假设你有一个 220V 的电源 🔌,但是你需要给一个 5V 的设备充电 📱,怎么办? 这时候就需要一个电压适配器,把 220V 的电压转换成 5V 的电压 ⚡!
代码示例:
// 目标接口:5V 电压
public interface Voltage5V {
int output5V(); // 输出 5V 电压
}
// 需要适配的类:220V 电压
public class Voltage220V {
public int output220V() {
int src = 220;
System.out.println("我是220V电压");
return src;
}
}
// 适配器类:电压适配器
public class VoltageAdapter extends Voltage220V implements Voltage5V {
@Override
public int output5V() {
// 获取 220V 电压
int srcV = output220V();
// 转换成 5V 电压
int dstV = srcV / 44;
return dstV;
}
}
// 客户端
public class Client {
public static void main(String[] args) {
VoltageAdapter adapter = new VoltageAdapter(); // 创建适配器对象
int voltage = adapter.output5V(); // 获取 5V 电压
System.out.println("输出电压为:" + voltage + "V"); // 输出电压
}
}
分析:
Voltage5V
是目标接口,客户端需要使用 5V 电压。Voltage220V
是需要适配的类,它只能输出 220V 电压。VoltageAdapter
是适配器类,它继承了Voltage220V
类,并实现了Voltage5V
接口,将 220V 电压转换成 5V 电压。
输出结果:
我是220V电压
输出电压为:5V
2. 对象适配器模式(插座转换器 🔌)
对象适配器模式,通过组合来实现适配,就像用一个插座转换器,把电器的插头转换成家里的插座可以使用的类型 🔌!
案例:还是电压适配器(对象版⚡)
还是上面的电压适配器的例子,但是这次我们使用对象适配器模式来实现 🚀!
代码示例:
// 目标接口:5V 电压
public interface Voltage5V {
int output5V(); // 输出 5V 电压
}
// 需要适配的类:220V 电压
public class Voltage220V {
public int output220V() {
int src = 220;
System.out.println("我是220V电压");
return src;
}
}
// 适配器类:电压适配器
public class VoltageAdapter implements Voltage5V {
private Voltage220V voltage220V; // 组合 220V 电压对象
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
// 获取 220V 电压
int srcV = voltage220V.output220V();
// 转换成 5V 电压
int dstV = srcV / 44;
return dstV;
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Voltage220V voltage220V = new Voltage220V(); // 创建 220V 电压对象
VoltageAdapter adapter = new VoltageAdapter(voltage220V); // 创建适配器对象
int voltage = adapter.output5V(); // 获取 5V 电压
System.out.println("输出电压为:" + voltage + "V"); // 输出电压
}
}
分析:
Voltage5V
是目标接口,客户端需要使用 5V 电压。Voltage220V
是需要适配的类,它只能输出 220V 电压。VoltageAdapter
是适配器类,它组合了Voltage220V
类,并实现了Voltage5V
接口,将 220V 电压转换成 5V 电压。
输出结果:
我是220V电压
输出电压为:5V
3. 接口适配器模式(万能插座 🗜️)
接口适配器模式,通过实现一个抽象类来实现适配,就像万能插座,可以兼容各种类型的插头 🗜️!
案例:USB 接口适配器(万能接口 💻)
假设你有一个 USB 设备 💾,但是你的电脑只有 Type-C 接口 💻,怎么办? 这时候就需要一个 USB 接口适配器,把 USB 接口转换成 Type-C 接口 💻!
代码示例:
// 目标接口:USB 接口
public interface Usb {
void read(); // 读取数据
void write(); // 写入数据
void connect(); // 连接设备
void disconnect(); // 断开连接
}
// 抽象适配器类:USB 适配器
public abstract class UsbAdapter implements Usb {
@Override
public void read() {
// 默认实现,可以不实现
}
@Override
public void write() {
// 默认实现,可以不实现
}
@Override
public void connect() {
// 默认实现,可以不实现
}
@Override
public void disconnect() {
// 默认实现,可以不实现
}
}
// 需要适配的类:Type-C 设备
public class TypeCDevice extends UsbAdapter {
@Override
public void read() {
System.out.println("Type-C 设备读取数据");
}
@Override
public void write() {
System.out.println("Type-C 设备写入数据");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
TypeCDevice typeCDevice = new TypeCDevice(); // 创建 Type-C 设备对象
typeCDevice.connect(); // 连接设备
typeCDevice.read(); // 读取数据
typeCDevice.write(); // 写入数据
typeCDevice.disconnect(); // 断开连接
}
}
分析:
Usb
是目标接口,客户端需要使用 USB 接口。UsbAdapter
是抽象适配器类,它实现了Usb
接口,但是提供了默认实现,子类可以选择性地实现需要的方法。TypeCDevice
是需要适配的类,它继承了UsbAdapter
类,并实现了read
和write
方法,实现了 USB 接口的功能。
输出结果:
Type-C 设备读取数据
Type-C 设备写入数据
四、 三种适配器的对比
特性 | 类适配器模式 | 对象适配器模式 | 接口适配器模式 |
---|---|---|---|
实现方式 | 继承 | 组合 | 抽象类 |
优点 | 简单易用 | 灵活,可以适配多个类 | 可以选择性地实现接口方法 |
缺点 | 只能适配一个类,耦合度较高 | 需要持有目标类的对象,增加了对象的数量 | 需要定义抽象类,增加了类的数量 |
适用场景 | 目标类接口比较稳定,不需要经常修改 | 需要适配多个类,或者目标类接口经常修改 | 只需要使用接口中的部分方法 |
五、 适配器模式的优缺点
优点:
- 提高类的复用性 ♻️!
- 提高系统的灵活性 🤸!
- 符合开闭原则 🆕!
- 解耦 🔗!
缺点:
- 增加了系统的复杂度 😫!
- 可能会降低性能 🐌!
六、 适配器模式的应用场景
- 接口转换: 将一个类的接口转换成客户希望的另外一个接口 🔌!
- 数据转换: 将一种格式的数据转换成另外一种格式的数据 🗂️!
- 遗留系统集成: 将新的系统和旧的系统集成在一起 🤝!
- 第三方库集成: 将第三方库集成到你的项目中 📚!