Design Pattern

Chapter 6 適配器模式(Adapter Pattern)

定義

把一個類的接口變換成客戶端所期待的另一種接口,而使原本兩個不匹配的接口可以一起工作。

組成

  1. 目標角色(Target):是期待得到的接口類型
  2. 適配器(Adapter):適配器類模式的核心,這個角色負責把源接口轉換成目標角色的接口
  3. 適配者(Adaptee):現有待適配的接口類型
  4. 客戶端(Client)

程式碼

Step1

public interface MediaPlayer {
    public void play(String audioType, String fileName);
}

public interface AdvancedMediaPlayer {
    public void playVlc(String fileName);
    public void playMp4(String fileName);
}

Step2

public class VlcPlayer implements AdvancedMediaPlayer{

    @Override
    public void playVlc(String fileName) {
        System.out.println("播放Vlc檔案:" + fileName);
    }
    @Override
    public void playMp4(String fileName) {
    }
}

public class Mp4Player implements AdvancedMediaPlayer{

    @Override
    public void playVlc(String fileName) {
    }
    @Override
    public void playMp4(String fileName) {
        System.out.println("播放Mp4檔案:" + fileName);    
    }
}

Step3

public class MediaAdapter implements MediaPlayer{
    AdvancedMediaPlayer advancedMusicPlayer;
    public MediaAdapter(String audioType){
        if(audioType.equalsIgnoreCase("vlc") ){
            advancedMusicPlayer = new VlcPlayer();
        }else if (audioType.equalsIgnoreCase("mp4")){
            advancedMusicPlayer = new Mp4Player();
        }    
    }

    @Override
    public void play(String audioType, String fileName) {
        if(audioType.equalsIgnoreCase("vlc")){
           advancedMusicPlayer.playVlc(fileName);
        }else if(audioType.equalsIgnoreCase("mp4")){
           advancedMusicPlayer.playMp4(fileName);
        }        
    }
}

Step4

public class AudioPlayer implements MediaPlayer{
    private MediaAdapter mediaAdapter;
    @Override
    public void play(String audioType, String fileName) {
        if(audioType.equalsIgnoreCase("mp3")){
           System.out.println("播放Mp3檔案:" + fileName);
        }else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){
           mediaAdapter = new MediaAdapter(audioType);
           mediaAdapter.play(audioType, fileName);
        }else{
           System.out.println("無效的檔案: 不支援" + audioType + "此檔案類型");
        }
    }
}

Step5

public static void main(String[] args) {
    AudioPlayer audioPlayer = new AudioPlayer();

    audioPlayer.play("mp3", "beyond the horizon.mp3");
    audioPlayer.play("mp4", "alone.mp4");
    audioPlayer.play("vlc", "far far away.vlc");
    audioPlayer.play("avi", "mind me.avi");
}

Step6(Output)

播放Mp3檔案:beyond the horizon.mp3
播放Mp4檔案:alone.mp4
播放Vlc檔案:far far away.vlc
無效的檔案: 不支援avi此檔案類型

優點

  1. 可以讓任何兩個沒有關聯的類一起運行。
  2. 增加了類的透明性和復用性。
  3. 靈活性和擴展性都非常好。

缺點

  1. 過多的使用適配器,會讓系統非常零亂。
  2. 由於JAVA 至多繼承一個類,所以至多只能適配一個適配者類,而且目標類必須是抽像類。