Loading

设计模式系列 - 适配器模式

见名知其意,适配器可用于对多个不兼容接口提供适配桥梁

介绍

适配器模式属于结构型模式。在现实世界中,这个模式适用的较为广泛,比如 DIY 一些电子产品,主要元器件提供的是标准接口,那么无论我们购买什么品牌的元器件,最终都能组装起来正常运行。

类图描述

由上图可知,我们通过定义 IAdvancedMediaPlayer 接口来约束 Mp4PlayerVlcPlayer 的播放行为。然后定义一个 适配器 MediaAdapter 来管理创建具体的某种类型的播放。AudioPlayer 为已支持的播放类型,然后在其内部通过调用适配器达到支持扩展类型的播放功能。

代码实现

1、定义扩展接口和受支持的类型

public interface IAdvancedMediaPlayer
{
    void PlayVlc(string fileNmae);
    void PlayMp4(string fileNmae);
}

public enum AudioType
{
    MP3,
    VLC,
    MP4,
    Unknown
}

2、定义具体类型的播放类

public class Mp4Player:IAdvancedMediaPlayer
{
    public void PlayVlc(string fileNmae)
    {
    }

    public void PlayMp4(string fileNmae)
    {
        Console.WriteLine($"Playing mp4 file.Name:{fileNmae}");
    }
}

public class VlcPlayer:IAdvancedMediaPlayer
{
    public void PlayVlc(string fileNmae)
    {
        Console.WriteLine($"Playing vlc file.Name:{fileNmae}");
    }

    public void PlayMp4(string fileNmae)
    {
    }
}

3、定义适配器

public class MediaAdapter:IMediaPlayer
{
    private IAdvancedMediaPlayer advancedMediaPlayer;

    public MediaAdapter(AudioType audioType)
    {
        switch (audioType)
        {
            case AudioType.VLC:
                advancedMediaPlayer = new VlcPlayer();
                break;
            case AudioType.MP4:
                advancedMediaPlayer = new Mp4Player();
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(audioType), audioType, null);
        }
    }

    public void Play(AudioType audioType, string fileName)
    {
        switch (audioType)
        {
            case AudioType.VLC:
                advancedMediaPlayer.PlayVlc(fileName);
                break;
            case AudioType.MP4:
                advancedMediaPlayer.PlayMp4(fileName);
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(audioType), audioType, null);
        }
    }
}

4、使用适配器

public  interface IMediaPlayer
{
    void Play(AudioType audioType, string fileName);
}

public class AudioPlayer:IMediaPlayer
{
    private IMediaPlayer mediaAdapter;
    public void Play(AudioType audioType, string fileName)
    {
        switch (audioType)
        {
            case AudioType.MP3:
                Console.WriteLine($"Playing mp3 file. Name:{fileName}");
                break;
            case AudioType.VLC:
            case AudioType.MP4:
                mediaAdapter = new MediaAdapter(audioType);
                mediaAdapter.Play(audioType, fileName);
                break;
            default:
                Console.WriteLine($"Invalid media.{audioType} format not supported");
                break;
        }
    }
}

5、上层调用

class Program
{
    static void Main(string[] args)
    {
        IMediaPlayer audioPlayer = new AudioPlayer();
        audioPlayer.Play(AudioType.MP3, "beyond the horizon.mp3");
        audioPlayer.Play(AudioType.MP4, "alone.mp4");
        audioPlayer.Play(AudioType.VLC, "far far away.vlc");
        audioPlayer.Play(AudioType.Unknown, "mind me.avi");

        Console.ReadKey();
    }
}

总结

适配器的使用一般是在已有的业务逻辑上进行扩展而来的,可以将任何没有关联的类联系起来,提高了代码的复用。但是在一个系统要从全局出发,不能过多的使用,否则会使系统非常混乱。

posted @ 2018-12-15 10:56  hippieZhou  阅读(440)  评论(0编辑  收藏  举报