适配器模式

24 阅读2分钟

适配器模式(Adapter Pattern)是一种常用的结构型设计模式,作为两个不兼容接口之间的桥梁。该模式涉及到一个被称为适配器(Adapter)的类,它充当了两个不兼容的接口之间的转换器,从而使得这两个接口可以协同工作。

适配器模式的来源并不仅仅在于程序设计,而是源自于日常生活中经常遇到的场景,例如电脑上提供的端口与要插入的接头不匹配时,我们就需要使用一个适配器将两边连接起来。

适配器模式的主要作用在于解决接口之间的兼容性问题,使得两个原本不兼容的接口可以协同工作。在应用程序开发中,适配器模式常被用于需要将现有的类或系统与新的接口进行适配的情况下。

public interface AdvancedMediaPlayer {
    public void playVlc(String fileName);
    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("Playing mp4 file. Name: "+ fileName);
    }
}

public class VlcPlayer implements AdvancedMediaPlayer{
    @Override
    public void playVlc(String fileName) {
        System.out.println("Playing vlc file. Name: "+ fileName);
    }

    @Override
    public void playMp4(String fileName) {
        //什么也不做
    }
}
public interface MediaPlayer {
    public void play(String audioType, String fileName);
}
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);
        }
    }
}
public class AudioPlayer implements MediaPlayer {
    MediaAdapter mediaAdapter;

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

        //播放 mp3 音乐文件的内置支持
        if(audioType.equalsIgnoreCase("mp3")){
            System.out.println("Playing mp3 file. Name: "+ fileName);
        }
        //mediaAdapter 提供了播放其他文件格式的支持
        else if(audioType.equalsIgnoreCase("vlc")
                || audioType.equalsIgnoreCase("mp4")){
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType, fileName);
        }
        else{
            System.out.println("Invalid media. "+
                    audioType + " format not supported");
        }
    }
}
public class AdapterPatternDemo {
    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");
    }
}

image.png

在 JDK 中,适配器模式(Adapter Pattern)的应用非常广泛,常见的适配器模式有以下几种:

1.InputStream/OutputStream 类与 Reader/Writer 类:

InputStream/OutputStream 类是字节流的抽象类,而 Reader/Writer 类是字符流的抽象类。这两个类之间并不兼容,在它们之间使用适配器设计模式进行转换,可实现将字节流转换为字符流,或将字符流转换为字节流。

2. MouseAdapter 类:

MouseAdapter 类是 java.awt.event 包中的一个适配器类,它实现了 MouseListener、MouseWheelListener、MouseMotionListener 接口,并给出了所有方法的空实现。因此,当我们需要监听鼠标事件时,可以继承这个适配器类,避免实现所有的接口方法。

3. KeyAdapter 类:

KeyAdapter 类是 java.awt.event 包中的一个适配器类,它实现了 KeyListener 接口,并给出了所有方法的空实现。因此,当我们需要监听键盘事件时,可以继承这个适配器类,避免实现所有的接口方法。

4. TimerTask 类:

java.util 包中的 TimerTask 类实现了 Runnable 接口,该类也是适配器模式的一个实现,可以将 TimerTask 实例对象传递给 Timer 对象,从而实现周期性任务的执行。