# Adapter 模式简介
适配器模式 ( Adapter Pattern
) 是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于 结构型模式,它结合了两个独立接口的功能。将一个类的接口转换成客户希望的另一个接口。使得原本由于接口不兼容而不能一起工作的类可以一起工作。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
举个栗子
现在手机充电接口开始向 Type-C
转变,但是市面上大多数充电线还是传统的接口,如果你有没有针对性的 Type-C
充电线,怎么办呐,答案是显而易见的用转接头,转换接口,从而可以利用传统数据线为 Type-C
接口的手机充电。适配器模式就是利用这个单一的类,充当转接头的作用,让其他的类,能够适配我们新的要求,而不用为了这个新标准而重构大量代码。
# 结构与分类
Adapeter
模式主要有两种类型 对象 Adapter 模式 和 类 Adapter 模式
# 对象 Adapter 模式
如下图所示,这种结构依赖于一个对象(适配对象)包含另外的一个对象(被适配的对象),就好比 UML 图中展示的那样,在派生类 Adapter 中引用 Adaptee (被适配对象),调用其中的相关函数,实现接口与结构的统一。
# 类 Adapter 模式
这种结构的通过 多继承的方式来实现 的一般从定义其接口的抽象类公开继承,从访问其实现的原有类私有继承,具体可参照下图
# 具体实现
音频播放器的扩展
- 我们有一个
IAudioPlayer
接口和一个实现了IAudioPlayer
接口的实体类AudioPlayer
。默认情况下,AudioPlayer
可以播放 mp3 格式的音频文件。 - 我们还有另一个接口
IAdvancedMediaPlayer
和实现了IAdvancedMediaPlayer
接口的实体类。该类可以播放wav
和ape
格式的高级音频文件。 - 我们想要让
AudioPlayer
播放其他格式的音频文件。为了实现这个功能,我们需要创建一个实现了IAudioPlayer
接口的适配器类AudioAdapter
, 并使用IAdvancedMediaPlayer
对象来播放所需的格式。 AudioPlayer
使用适配器类AudioAdapter
传递所需的音频类型,不需要知道能播放所需格式音频的实际类。Adapter Pattern
,我们的演示类使用AudioPlayer
类来播放各种格式。
具体 UML 类图如下 直接在 VS2015 的建模项目里画的,方便我直接生成部分代码,与标准 UML 图可能有差异
# Step1: 为音频播放器和更高级的音频播放器创建接口
IAudioPlayre.cs
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Adapter_Pattern_适配器模式_ | |
{ | |
public interface IAudioPlayer | |
{ | |
void player(string audioType, string fileName); | |
} | |
} |
IAdvanceAudioPlayer.cs
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Adapter_Pattern_适配器模式_ | |
{ | |
// 高级音频格式播放 | |
public interface IAdvanceAudioPlayer | |
{ | |
void playWav(string fileName); | |
void playApe(string fileName); | |
} | |
} |
# Step2: 创建实现了 IAdvancedMediaPlayer
接口的实体类
WavPlayer.cs
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Adapter_Pattern_适配器模式_ | |
{ | |
class WavPlayer : IAdvanceAudioPlayer | |
{ | |
public void playApe(string fileName) | |
{ | |
// 什么也不做 | |
throw new NotImplementedException(); | |
} | |
public void playWav(string fileName) | |
{ | |
Console.WriteLine("Playing wav file. Name:" + fileName); | |
} | |
} | |
} |
ApePlayer.cs
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Adapter_Pattern_适配器模式_ | |
{ | |
class ApePlayer : IAdvanceAudioPlayer | |
{ | |
public void playApe(string fileName) | |
{ | |
Console.WriteLine("Playing ape file. Name:" + fileName); | |
} | |
public void playWav(string fileName) | |
{ | |
// 什么也不做 | |
throw new NotImplementedException(); | |
} | |
} | |
} |
# Step3: 创建实现了 AduioPlayer
接口的适配器
AudioAdapter.cs
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Adapter_Pattern_适配器模式_ | |
{ | |
// 高级音频播放的适配器 | |
class AudioAdapter : IAudioPlayer | |
{ | |
private IAdvanceAudioPlayer advancedAudioPlayer; | |
public AudioAdapter (string audioType) | |
{ | |
if(audioType=="ape") | |
{ | |
advancedAudioPlayer = new ApePlayer(); | |
} | |
else if(audioType =="wav") | |
{ | |
advancedAudioPlayer = new WavPlayer(); | |
} | |
} | |
public void player(string audioType, string fileName) | |
{ | |
if(audioType=="ape") | |
{ | |
advancedAudioPlayer.playApe(fileName); | |
} | |
else if(audioType=="wav") | |
{ | |
advancedAudioPlayer.playWav(fileName); | |
} | |
} | |
} | |
} |
# Step4: 创建实现了 AudioPlayer
接口的基本音频格式播放的实体类
AudioPlayer.cs
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Adapter_Pattern_适配器模式_ | |
{ | |
class AudioPlayer : IAudioPlayer | |
{ | |
private AudioAdapter audioAdapter; | |
public void player(string audioType, string fileName) | |
{ | |
if(audioType=="mp3") | |
{ | |
Console.WriteLine("Playing mp3 file. Name:" + fileName); | |
} | |
else if(audioType=="ape"||audioType=="wav") | |
{ | |
audioAdapter = new AudioAdapter(audioType); | |
audioAdapter.player(audioType, fileName); | |
} | |
else | |
{ | |
Console.WriteLine("Invalid audio. " + audioType + " format not supported"); | |
} | |
} | |
} | |
} |
# Step5: 一个驱动类利用 AudioPlayer
来播放不同格式的音频文件
AdapterPattern.cs
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Adapter_Pattern_适配器模式_ | |
{ | |
class AdapterPattern | |
{ | |
static void Main(string[] args) | |
{ | |
AudioPlayer audioPlayer = new AudioPlayer(); | |
audioPlayer.player("mp3", "beyond the horizon.mp3"); | |
audioPlayer.player("wav", "alone.wav"); | |
audioPlayer.player("ape", "my heart will go on.ape"); | |
audioPlayer.player("vlc", "far far away.vlc"); | |
} | |
} | |
} |
输出结果
Playing mp3 file. Name:beyond the horizon.mp3
Playing wav file. Name:alone.wav
Playing ape file. Name:my heart will go on.ape
Invalid audio. vlc format not supported
# 样例代码下载地址
适配器模式(Adapter Pattern)示例代码