适配器模式
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 71 课,共 87 课。
适配器模式是一种结构型设计模式,可以让不兼容的接口协同工作。它充当两个类之间的桥梁,将一个类的接口转换为客户端所需的接口。你可以把它想象成电源适配器,它能让你把欧洲的设备插入美国的插座。
想象一下,你有一个现有的 MediaPlayer 接口,用来播放音频文件,但你需要集成一个第三方库,它使用完全不同的接口来播放视频:
// 你的代码使用的现有接口
interface MediaPlayer {
void play(String filename);
}
// 接口不兼容的第三方类
class AdvancedVideoPlayer {
public void playVideo(String filename) {
System.out.println("Playing video: " + filename);
}
}适配器包装不兼容的类并实现预期的接口,在它们之间转换调用:
class VideoPlayerAdapter implements MediaPlayer {
private AdvancedVideoPlayer videoPlayer;
public VideoPlayerAdapter() {
this.videoPlayer = new AdvancedVideoPlayer();
}
public void play(String filename) {
videoPlayer.playVideo(filename);
}
}现在,你的客户端代码可以通过熟悉的 MediaPlayer 接口使用视频播放器:
MediaPlayer player = new VideoPlayerAdapter();
player.play("movie.mp4"); // 输出:Playing video: movie.mp4在集成旧代码或第三方库时,适配器模式非常有用,因为你无需修改它们的源代码。客户端无需知道自己正在使用经过适配的类,只需使用它熟悉的接口即可。
挑战
简单让我们使用适配器模式构建一个温度转换系统!你有一个现有的天气应用,它使用摄氏温度,但你需要接入一个只能输出华氏温度读数的旧版温度传感器。你无需修改任何一个系统,只需创建一个适配器来弥合两者之间的差异。
你将把代码分成 4 个文件:
TemperatureProvider.java:定义天气应用所需的接口。该接口应声明一个方法getTemperatureCelsius(),返回一个表示摄氏温度的 double 值。FahrenheitSensor.java:表示接口不兼容的旧版传感器。创建一个类,其中包含一个私有 double 字段,用于存储华氏温度,并通过构造函数设置该字段。该类应有一个方法readFahrenheit(),用于返回存储的华氏温度值。SensorAdapter.java:创建适配器,让华氏温度传感器能够与天气应用兼容。你的适配器应实现TemperatureProvider,并封装一个FahrenheitSensor。调用getTemperatureCelsius()时,它应从传感器读取温度,并使用以下公式将其转换为摄氏温度:(fahrenheit - 32) * 5 / 9。Main.java:把所有部分组合起来!你会收到一个输入:华氏温度读数(double)。使用输入值创建一个
FahrenheitSensor。然后创建一个封装该传感器的SensorAdapter。将适配器存储在一个TemperatureProvider变量中,以展示天气应用可以通过预期的接口使用它。按以下格式输出结果:
Temperature: [celsius] C,其中 celsius 格式为小数点后一位。
你会收到一个输入:华氏温度(double)。
例如,输入 98.6 时,输出为:
Temperature: 37.0 C注意,Main 类完全通过 TemperatureProvider 接口工作。它并不知道实际温度来自一个在幕后经过适配的华氏温度传感器。这就是适配器模式的精妙之处!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double fahrenheit = scanner.nextDouble();
// TODO: 用输入值创建一个 FahrenheitSensor
// TODO: 创建一个封装该传感器的 SensorAdapter
// TODO: 将适配器存入一个 TemperatureProvider 变量
// TODO: 获取摄氏温度并打印
// 格式:保留一位小数,输出 "Temperature: [celsius] C"
// 提示:使用 String.format("%.1f", value) 设置格式
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器