生活中经常会到这种问题,例如中国的标准电压是220v,美国则是110v。如果想要在美国使用中国的电器,我们需要有一个电压适配器作为中间桥梁进行电压的转换。

适配器模式就是这样的功能,是两个不兼容的接口的桥梁,属于一种结构型模式,结合了两个接口的功能。

现在有一个媒体播放器,有两个子类,一个播放器可以播放mp4格式文件,一个可以播放vlc格式文件:

/**
 * 播放器接口
 * @author 樱桃肉丸子
 */
public interface AdvancedMediaPlayer {

    void playVlc(String fileName);
    void playMp4(String fileName);

}
/**
 * MP4播放器
 * @author 樱桃肉丸子
 */
public class Mp4Player implements AdvancedMediaPlayer {
    @Override
    public void playVlc(String fileName) {
        //do nothing
    }

    @Override
    public void playMp4(String fileName) {
        System.out.println("mp4播放");
    }
}
/**
 * VLC播放器
 * @author 樱桃肉丸子
 */
public class VlcPlayer implements AdvancedMediaPlayer {
    @Override
    public void playVlc(String fileName) {
        System.out.println("VLC播放");
    }

    @Override
    public void playMp4(String fileName) {
        //do nothing
    }
}

至此,我们现在可以播放mp4和vlc格式的文件了,但是此时有一个更高的要求,就是希望有一个播放器可以同时播放mp4和vlc格式的文件,此时创建一个接口来表示更高级的播放器:

/**
 * 更高级的播放器接口
 * @author 樱桃肉丸子
 */
public interface MediaPlayer {
    void play(String audioType, String fileName);
}

此时,我们需要创建一个适配器。这个适配器可以根据我们的需求自动转换为响应的播放器 。

/**
 * 适配器实现类
 * @author 樱桃肉丸子
 */
public class MediaAdapter implements MediaPlayer{

    AdvancedMediaPlayer advancedMediaPlayer;

    public MediaAdapter(String audioType){
        if(audioType.equalsIgnoreCase("vlc") ){
            advancedMediaPlayer = new VlcPlayer();
        } else if (audioType.equalsIgnoreCase("mp4")){
            advancedMediaPlayer = new Mp4Player();
        }
    }

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

此时创建高级播放器的子类来实现播放的功能。该类通过适配器达到灵活播放的效果。

/**
 * 自动播放器
 * @author 樱桃肉丸子
 */
public class AudioPlayer implements MediaPlayer {

    MediaAdapter mediaAdapter;


    @Override
    public void play(String audioType, String fileName) {

        //内置mp3播放器
        if("mp3".equalsIgnoreCase(audioType)){
            System.out.println("播放mp3文件");
        //mp4或vlc格式文件
        }else if("mp4".equalsIgnoreCase(audioType) || "vlc".equalsIgnoreCase(audioType)){
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType, fileName);
        }else{
            System.out.println("系统暂不支持该类型文件的播放!!!");
        }


    }
}

最后看一下效果:

/**
 * 测试类
 * @author 樱桃肉丸子
 */
public class AdapterPatternDemo {

    public static void main(String[] args) {
        //播放mp4文件
        MediaPlayer mediaPlayer = new AudioPlayer();
        mediaPlayer.play("mp4","a.mp3");
        //播放vlc文件
        mediaPlayer.play("vlc","b.vlc");


    }
}


总结:

在这个例子中,mp4和vlc两个接口本不兼容,但是通过适配器中的灵活调用,使新的播放器同时具有了两种功能。从功能层面上可以在AutoPlayer直接将适配器的代码写入,但鄙人认为将这种兼容性的代码单独封装会好一点呢。