# Adapter 模式简介

适配器模式 ( Adapter Pattern ) 是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于 结构型模式,它结合了两个独立接口的功能。将一个类的接口转换成客户希望的另一个接口。使得原本由于接口不兼容而不能一起工作的类可以一起工作。

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

举个栗子

现在手机充电接口开始向 Type-C 转变,但是市面上大多数充电线还是传统的接口,如果你有没有针对性的 Type-C 充电线,怎么办呐,答案是显而易见的用转接头,转换接口,从而可以利用传统数据线为 Type-C 接口的手机充电。适配器模式就是利用这个单一的类,充当转接头的作用,让其他的类,能够适配我们新的要求,而不用为了这个新标准而重构大量代码。

# 结构与分类

Adapeter 模式主要有两种类型 对象 Adapter 模式类 Adapter 模式

# 对象 Adapter 模式

如下图所示,这种结构依赖于一个对象(适配对象)包含另外的一个对象(被适配的对象),就好比 UML 图中展示的那样,在派生类 Adapter 中引用 Adaptee (被适配对象),调用其中的相关函数,实现接口与结构的统一。

Adapter_Pattern_UML

# 类 Adapter 模式

这种结构的通过 多继承的方式来实现 的一般从定义其接口的抽象类公开继承,从访问其实现的原有类私有继承,具体可参照下图

Adapter_Pattern_Class_UML

# 具体实现

音频播放器的扩展

  1. 我们有一个 IAudioPlayer 接口和一个实现了 IAudioPlayer 接口的实体类 AudioPlayer 。默认情况下, AudioPlayer 可以播放 mp3 格式的音频文件。
  2. 我们还有另一个接口 IAdvancedMediaPlayer 和实现了 IAdvancedMediaPlayer 接口的实体类。该类可以播放 wavape 格式的高级音频文件。
  3. 我们想要让 AudioPlayer 播放其他格式的音频文件。为了实现这个功能,我们需要创建一个实现了 IAudioPlayer 接口的适配器类 AudioAdapter , 并使用 IAdvancedMediaPlayer 对象来播放所需的格式。
  4. AudioPlayer 使用适配器类 AudioAdapter 传递所需的音频类型,不需要知道能播放所需格式音频的实际类。 Adapter Pattern ,我们的演示类使用 AudioPlayer 类来播放各种格式。

具体 UML 类图如下 直接在 VS2015 的建模项目里画的,方便我直接生成部分代码,与标准 UML 图可能有差异

Adapter-Patterneg

# 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

# 样例代码下载地址

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Seiun 微信支付

微信支付

Seiun 支付宝

支付宝