(6).适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的类协同工作。通过创建一个适配器类,将一个类的接口转换成客户端所期望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

适配器模式的基本结构

  1. Target: 定义客户端使用的接口。
  2. Adaptee: 需要适配的现有类,它有一个与Target不兼容的接口。
  3. Adapter: 将Adaptee的接口转换成Target接口,使它们能够协同工作。
  4. Client: 使用Target接口的客户端代码。

示例场景

假设我们有一个现有的AudioPlayer类,它可以播放MP3格式的音频文件。但现在我们需要让它支持其他格式的音频文件(如VLC支持的格式),而不需要修改AudioPlayer类本身。我们可以使用适配器模式来实现这一点。

示例代码

1. Target 接口

// 定义客户端使用的接口
public interface IAdvancedMediaPlayer
{
    void PlayVlc(string fileName);
    void PlayMp4(string fileName);
}

2. Adaptee 类

// 现有的类,具有与Target不兼容的接口
public class VlcPlayer : IAdvancedMediaPlayer
{
    public void PlayVlc(string fileName)
    {
        Console.WriteLine($"Playing VLC file: {fileName}");
    }

    public void PlayMp4(string fileName)
    {
        // 不支持MP4
        throw new NotImplementedException();
    }
}

public class Mp4Player : IAdvancedMediaPlayer
{
    public void PlayVlc(string fileName)
    {
        // 不支持VLC
        throw new NotImplementedException();
    }

    public void PlayMp4(string fileName)
    {
        Console.WriteLine($"Playing MP4 file: {fileName}");
    }
}

3. Adapter 类

// 适配器类,将Adaptee的接口转换为Target接口
public class MediaAdapter : IMediaPlayer
{
    private IAdvancedMediaPlayer _advancedMusicPlayer;

    public MediaAdapter(string audioType)
    {
        if (audioType.Equals("vlc", StringComparison.OrdinalIgnoreCase))
        {
            _advancedMusicPlayer = new VlcPlayer();
        }
        else if (audioType.Equals("mp4", StringComparison.OrdinalIgnoreCase))
        {
            _advancedMusicPlayer = new Mp4Player();
        }
    }

    public void Play(string audioType, string fileName)
    {
        if (audioType.Equals("vlc", StringComparison.OrdinalIgnoreCase))
        {
            _advancedMusicPlayer.PlayVlc(fileName);
        }
        else if (audioType.Equals("mp4", StringComparison.OrdinalIgnoreCase))
        {
            _advancedMusicPlayer.PlayMp4(fileName);
        }
    }
}

4. Target 接口

// 定义客户端使用的接口
public interface IMediaPlayer
{
    void Play(string audioType, string fileName);
}

5. Client 类

// 使用适配器的客户端代码
public class AudioPlayer : IMediaPlayer
{
    private MediaAdapter _mediaAdapter;

    public void Play(string audioType, string fileName)
    {
        // 内置支持的音频类型
        if (audioType.Equals("mp3", StringComparison.OrdinalIgnoreCase))
        {
            Console.WriteLine($"Playing MP3 file: {fileName}");
        }
        // 其他音频类型需要适配器
        else if (audioType.Equals("vlc", StringComparison.OrdinalIgnoreCase) || audioType.Equals("mp4", StringComparison.OrdinalIgnoreCase))
        {
            _mediaAdapter = new MediaAdapter(audioType);
            _mediaAdapter.Play(audioType, fileName);
        }
        else
        {
            Console.WriteLine($"Invalid media format: {audioType}");
        }
    }
}

6. 测试代码

class Program
{
    static void Main(string[] args)
    {
        IMediaPlayer audioPlayer = new AudioPlayer();

        // 播放MP3文件
        audioPlayer.Play("mp3", "beyond_the_horizon.mp3");

        // 播放VLC文件
        audioPlayer.Play("vlc", "forest.vlc");

        // 播放MP4文件
        audioPlayer.Play("mp4", "alone.mp4");

        // 尝试播放不支持的格式
        audioPlayer.Play("avi", "movie.avi");
    }
}

输出结果

Playing MP3 file: beyond_the_horizon.mp3
Playing VLC file: forest.vlc
Playing MP4 file: alone.mp4
Invalid media format: avi

详细说明

  1. IMediaPlayer 接口:
    • 定义了客户端使用的接口,允许播放不同类型的音频文件。
  2. AudioPlayer 类:
    • 这是客户端使用的类,支持播放MP3文件,并通过适配器支持其他类型的音频文件。
  3. IAdvancedMediaPlayer 接口:
    • 定义了高级媒体播放器的接口,支持播放VLC和MP4文件。
  4. VlcPlayer 和 Mp4Player 类:
    • 这些是现有的类,具有与IMediaPlayer不兼容的接口。
  5. MediaAdapter 类:
    • 这是适配器类,将VlcPlayerMp4Player的接口转换为IMediaPlayer接口。
  6. 客户端代码:
    • 客户端代码通过AudioPlayer类播放不同类型的音频文件,而无需关心具体的实现细节。

适配器模式的优点

  1. 提高复用性:通过适配器,可以重用现有的类,而不需要修改它们的代码。
  2. 开闭原则:可以在不修改现有代码的情况下,引入新的适配器来支持新的功能。
  3. 简化接口:将复杂的接口转换为简单的接口,使得客户端代码更容易使用。

适配器模式的缺点

  1. 增加复杂性:引入适配器类可能会增加系统的复杂性。
  2. 性能开销:适配器可能会影响性能,尤其是在需要频繁转换的情况下。

总结

适配器模式适用于以下场景:
  • 需要使用一些已经存在的类,但其接口不符合当前的需求。
  • 希望创建一个可以复用的类,该类可以与其他不兼容的类或接口一起工作。
  • 需要在系统中动态地添加对新功能的支持,而不修改现有代码。
posted @ 2025-03-15 21:06  小码哥-风云  阅读(15)  评论(0)    收藏  举报