1. 程式人生 > >設計模式系列 - 介面卡模式

設計模式系列 - 介面卡模式

見名知其意,介面卡可用於對多個不相容介面提供適配橋樑

介紹

介面卡模式屬於結構型模式。在現實世界中,這個模式適用的較為廣泛,比如 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();
    }
}

總結

介面卡的使用一般是在已有的業務邏輯上進行擴充套件而來的,可以將任何沒有關聯的類聯絡起來,提高了程式碼的複用。但是在一個系統要從全域性出發,不能過多的使用,否則會使系統非常混亂。