Menu
CoddyTech

适配器模式

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 95 课,共 110 课。

适配器模式可以让不兼容的接口协同工作。它充当两个原本无法协作的类之间的桥梁,用客户端所需的新接口包装现有类。在将第三方库或旧代码集成到应用程序时,这种模式尤其有用。

假设你有一个处理 JSON 数据的系统,但需要集成一个只输出 XML 的组件。你不修改任何一个类,而是创建一个适配器,在它们之间进行转换:

// 系统需要的现有接口
abstract class JsonData {
  String getJson();
}

// 接口不兼容的旧类
class XmlService {
  String getXml() {
    return '<data><name>John</name></data>';
  }
}

// 适配器让 XmlService 与 JsonData 兼容
class XmlToJsonAdapter implements JsonData {
  final XmlService _xmlService;

  XmlToJsonAdapter(this._xmlService);

  @override
  String getJson() {
    String xml = _xmlService.getXml();
    // 将 XML 转换为 JSON(简化版)
    return '{"name": "John"}';
  }
}

void main() {
  var xmlService = XmlService();
  var adapter = XmlToJsonAdapter(xmlService);

  print(adapter.getJson());  // {"name": "John"}
}

XmlToJsonAdapter 封装了 XmlService,并实现了 JsonData 接口。客户端代码可以使用熟悉的 JsonData 接口,而无需知道数据最初来自 XML 源。适配器会在内部处理所有转换。

当你想使用现有的类,但它的接口与你需要的不匹配,或者需要创建一个可与接口不兼容的类协作的可复用类时,可以使用适配器模式。

challenge icon

挑战

简单

让我们来构建一个媒体播放器适配器系统!想象一下,你有一个现代音频系统,它要求所有媒体源都通过标准接口提供音频,但你需要接入一台老式黑胶唱机,而它产生声音的方式完全不同。

你将创建两个文件来组织适配器模式的实现:

  • media_adapter.dart:这个文件包含接口和适配器类。定义一个抽象类 AudioSource,这是现代系统所要求的接口。它应该包含一个方法 String playAudio(),以字符串形式返回音频输出。然后创建一个代表旧式设备的 VinylPlayer 类,它有一个 trackName 字段,以及一个方法 String spinRecord(),该方法返回 *crackle* Playing vinyl: [trackName] *crackle*。最后,构建一个实现 AudioSource 并包装 VinylPlayer 的 VinylAdapter。适配器的 playAudio() 方法应该调用黑胶唱机的 spinRecord() 方法并返回结果,从而连接不兼容的接口。
  • main.dart:导入媒体适配器文件,并演示适配器如何让旧式黑胶唱机与依赖现代 AudioSource 接口的代码协同工作。创建一个曲目名称为 Bohemian Rhapsody 的 VinylPlayer。然后创建一个包装这台黑胶唱机的 VinylAdapter。将适配器存储在一个类型为 AudioSource 的变量中,以证明它符合预期的接口。在音频源上调用 playAudio() 并打印结果。

这种模式的妙处在于,你的主代码可以使用标准的 AudioSource 接口,而不必知道幕后实际工作的是一台旧式黑胶唱机!

预期输出:

*crackle* Playing vinyl: Bohemian Rhapsody *crackle*

亲手试试

import 'media_adapter.dart';

void main() {
  // TODO:创建一个 VinylPlayer,曲目名称为 "Bohemian Rhapsody"
  
  // TODO:创建一个 VinylAdapter,封装该黑胶唱片播放器
  
  // TODO:将适配器存入一个 AudioSource 类型的变量
  
  // TODO:在你的音频源上调用 playAudio(),并打印结果
  
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器