适配器模式
本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 57 课,共 70 课。
适配器模式是一种结构型模式,能够让不兼容的接口协同工作。它充当两个类之间的桥梁,将一个类的接口转换为客户端所期望的接口。你可以把它想象成一个电源适配器,让你能把欧洲的设备插入美国的插座。
当你想使用现有的类,但它的接口与你的代码需求不匹配时,这种模式特别有用。你可以创建一个适配器来包装它,而不是修改原来的类(你可能无法控制它):
// 现有类的接口不兼容
public class OldPrinter
{
public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}
// 你的代码所需的接口
public interface IPrinter
{
void Print(string text);
}
// 适配器连接两个接口
public class PrinterAdapter : IPrinter
{
private OldPrinter _oldPrinter;
public PrinterAdapter(OldPrinter oldPrinter)
{
_oldPrinter = oldPrinter;
}
public void Print(string text)
{
_oldPrinter.PrintMessage(text); // 委托给旧接口处理
}
}现在,你的代码可以通过预期的接口与旧打印机配合工作:
OldPrinter legacy = new OldPrinter();
IPrinter printer = new PrinterAdapter(legacy);
printer.Print("Hello"); // 旧版:Hello在将第三方库或旧版代码集成到应用程序时,适配器模式非常有用。客户端代码通过 IPrinter 接口进行操作,完全不知道幕后实际执行工作的类是一个旧版且不兼容的类。
挑战
简单让我们使用适配器模式构建一个媒体播放器系统。你有一个现成的音频库,可以播放 MP3 文件,但你的应用需要一个能够处理不同媒体类型的统一接口。你将创建一个适配器来弥合这一差距,让现代媒体播放器能够与旧版音频库无缝协作。
你将把代码分成三个文件:
LegacyAudio.cs:这是一个你无法修改的现有库。在MediaSystem命名空间中创建一个LegacyAudioPlayer类,其中包含一个PlayMp3(string filename)方法,该方法返回字符串"Playing MP3: {filename}"。这是你的“被适配者”,也就是接口不兼容的类。MediaAdapter.cs:在同一个命名空间中创建接口和适配器。定义一个IMediaPlayer接口,其中包含一个返回字符串的Play(string filename)方法。然后创建一个实现IMediaPlayer的MediaPlayerAdapter类。你的适配器应包装一个LegacyAudioPlayer实例(通过构造函数传入),并将Play调用转换为旧版播放器的PlayMp3方法调用。Program.cs:创建旧版播放器,用你的适配器包装它,并通过IMediaPlayer接口使用适配器,将所有内容整合起来。这展示了客户端代码如何使用现代接口,同时由适配器在幕后处理与旧版系统的通信。
你将收到一个输入:
- 要播放的文件名(例如,
song.mp3)
创建一个 LegacyAudioPlayer,用 MediaPlayerAdapter 包装它,然后通过 IMediaPlayer 接口在适配器上调用 Play,并打印结果。
例如,如果输入是 favorite_track.mp3,输出应为:
Playing MP3: favorite_track.mp3这种模式的优点在于,你的主代码只与 IMediaPlayer 交互,它完全不知道实际工作是由旧版音频库完成的!如果你之后需要支持另一个旧版库,只需创建一个新的适配器,无需更改任何客户端代码!
亲手试试
using System;
using MediaSystem;
class Program
{
public static void Main(string[] args)
{
// 读取输入的文件名
string filename = Console.ReadLine();
// TODO: 创建一个 LegacyAudioPlayer 实例
// TODO: 用 MediaPlayerAdapter 包装它
// TODO: 通过 IMediaPlayer 接口使用适配器
// 并打印以文件名为参数调用 Play 的结果
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C# 在线编译器