zoukankan      html  css  js  c++  java
  • 1.7(设计模式)适配器模式

    适配器主要解决适配问题,即将一些由于接口不兼容不能一起工作的类可以在一起工作。

    例如插座上是220v的电压,手机充电需要5v的电压,这时手机和插座直接就通过一个适配器(充电器)连接起来了。

    例如一个音频播放器只能播放MP3格式的文件,我们通过一个适配器将其连接到高级播放器上,

    当前音频播放器不支持的格式(MP4、VLC)转交给高级播放器播放,使其能播放更多格式。

    下面就媒体播放器这个例子看下对应代码:

    媒体文件类型

    public enum AudioTypeEnum {
        MP3,VLC,MP4
    }

    高级媒体播放器接口,可以播放MP4/VLC格式的文件。后续高级媒体播放器与媒体播放器通过适配器连接,使媒体播放器可以支持更多格式。

    这个接口和实现类可以暂且不看,等后续添加适配器的时候再看这一部分。

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

    高级媒体播放器 播放MP4格式文件的具体实现类

    public class Mp4Play implements AdvanceMediaPlay{
    
        @Override
        public void playMp4(String fileName) {
            System.out.println("play mp4:" + fileName);
        }
    
        @Override
        public void playVlc(String fileName) {}
        
    }

    高级媒体播放器 播放VLC格式的具体实现类

    public class VlcPlay implements AdvanceMediaPlay{
    
        @Override
        public void playMp4(String fileName) {}
    
        @Override
        public void playVlc(String fileName) {
            System.out.println("play vlc:" + fileName);
        }
    
    }

     (上述部分可暂且忽略,等后续添加适配器时再查看)

     -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    媒体播放器接口,主要包含播放方法,方法参数:媒体文件类型(MP3、MP4、VLC),文件名

    public interface MediaPlay {
        public void paly(AudioTypeEnum audioType, String fileName);
    }

    实现媒体播放接口的音频播放器,音频播放器只能实现播放MP3格式的文件。

    public class AudioPlay implements MediaPlay{
        //private MediaAdapter mediaAdapter;
    
        
        public void paly(AudioTypeEnum audioType, String fileName) {
            
            switch(audioType) {
            case MP3://内置MP3播放器
                System.out.println("play mp3:" + fileName);
                break;
            case MP4://TODO 其他可播放类型,采用适配器播放
    
            default://TODO 无法播放部分抛出异常
                try {
                    throw new Exception("播放异常,格式不支持!");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }    
    }

    我们先来看下没有添加适配器,只能播放MP3格式的情况,此时将高级媒体播放器看做与其无关的一个个体。

    目前有两个个体,一个是音频播放器,一个是高级媒体播放器。

    测试音频播放器

    public class Main {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            MediaPlay mediaPlay = new AudioPlay();
            mediaPlay.paly(AudioTypeEnum.MP4, "mmm4");
            mediaPlay.paly(AudioTypeEnum.MP3, "mmm3");
            mediaPlay.paly(AudioTypeEnum.VLC, "fff");
        }
    
    }
    java.lang.Exception: 播放异常,格式不支持!
    play mp3:mmm3
        at com.design.adapter.AudioPlay.paly(AudioPlay.java:20)
        at com.design.adapter.Main.main(Main.java:8)
    java.lang.Exception: 播放异常,格式不支持!
        at com.design.adapter.AudioPlay.paly(AudioPlay.java:20)
        at com.design.adapter.Main.main(Main.java:10)

     可以看到,只有音频播放器支持的MP3格式可以正常播放,其他格式都无法播放。

    此时有一个高级媒体播放器可以播放其他类型的媒体文件,我们有没有什么办法将音频播放器和高级媒体播放器联系起来?

    当然有,那就是适配器。

    现在我们想通过一个适配器将两者联系起来,让音频播放器可以通过高级媒体播放器播放更多类型的信息。

    既然适配器是对传入音频播放器的文件进行适配,将其适配到高级媒体播放器中播放,那么首先适配器需要和音频播放器一样实现MediaPlay接口。

    public class MediaAdapter implements MediaPlay{
        
        public MediaAdapter(AudioTypeEnum audioTypeEnum) {
           
        }
        
        @Override
        public void paly(AudioTypeEnum audioType, String fileName) {
            
        }
    }

    适配器最终是调用高级媒体播放器播放文件,最终播放具体文件还是高级媒体播发器接口的实现类来完成的。

    所有在创建适配器对象时,我们可以根据文件类型,实例化一个播放该文件的播放器。

    public class MediaAdapter implements MediaPlay{
        AdvanceMediaPlay advanceMediaPlay;
        //根据类型,适配对应对象,最后通过具体对象播放文件
        public MediaAdapter(AudioTypeEnum audioTypeEnum) {
            switch (audioTypeEnum) {//是什么类型的对象,就实例化什么类型的播放器
            case MP4:advanceMediaPlay = new Mp4Play();
                break;
            case VLC:advanceMediaPlay = new VlcPlay();
                break;
            default:
                try {
                    throw new Exception("播放类型异常!");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
        //根据类型,适配对应方法
        @Override
        public void paly(AudioTypeEnum audioType, String fileName) {
            
        }
    }

    具体的播放对象实例完成后,我们来看看paly方法,现在确定了基本的思路。音频播放器将不支持的文件传递给适配器,

    适配器调用对应的播放器来播放文件。

    AdvanceMediaPlay 中有playMp4和palyVlc两个播放方法,这时在适配器的paly中需要根据文件类型,调用对用的方法。

    例如实例化适配器时传递进来的文件类型是MP4,实例的是播放MP4的播放器,调用play方法时调用的应该是palyMp4。

    在播放MP4格式的播放器中调用playVlc方法显然是不正确的。

    public class MediaAdapter implements MediaPlay{
        AdvanceMediaPlay advanceMediaPlay;
        //根据类型,适配对应对象
        public MediaAdapter(AudioTypeEnum audioTypeEnum) {
            switch (audioTypeEnum) {//根据文件类型,实例化对应类型播放器
            case MP4:advanceMediaPlay = new Mp4Play();
                break;
            case VLC:advanceMediaPlay = new VlcPlay();
                break;
            default:
                try {
                    throw new Exception("播放类型异常!");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
        //根据类型,适配对应方法
        @Override
        public void paly(AudioTypeEnum audioType, String fileName) {
            switch(audioType) {//根据文件类型调用对应方法
            case MP4:
                advanceMediaPlay.playMp4(fileName);
                break;
            case VLC:
                advanceMediaPlay.playVlc(fileName);
                break;
            default:
                try {
                    throw new Exception("播放异常!");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    适配器完成后,我们就在音频播放器中添加上适配器

    public class AudioPlay implements MediaPlay{
        private MediaAdapter mediaAdapter;//适配器
    
        
        public void paly(AudioTypeEnum audioType, String fileName) {
            // TODO Auto-generated method stub
            switch(audioType) {
            case MP3://内置MP3播放器
                System.out.println("play mp3:" + fileName);
                break;
            case MP4://TODO 其他可播放类型,采用适配器播放
            case VLC:
                mediaAdapter = new MediaAdapter(audioType);//实例化适配器,适配器会根据类型实例化对应播放器
                mediaAdapter.paly(audioType, fileName);//播放时,会根据对应播放器调用对应方法。
                break;
            default://TODO 无法播放部分抛出异常
                try {
                    throw new Exception("播放异常,格式不支持!");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }    
    }

    测试添加适配器后的音频播放器

    public class Main {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            MediaPlay mediaPlay = new AudioPlay();
            mediaPlay.paly(AudioTypeEnum.MP4, "mmm4");
            mediaPlay.paly(AudioTypeEnum.MP3, "mmm3");
            mediaPlay.paly(AudioTypeEnum.VLC, "fff");
        }
    
    }
    运行结果:
    play mp4:mmm4 play mp3:mmm3 play vlc:fff

    参考资料:

    https://www.runoob.com/design-pattern/adapter-pattern.html

    https://www.cnblogs.com/V1haoge/p/6479118.html

  • 相关阅读:
    LBS 经纬度定位
    LBS 经纬度定位
    GPS定位基本原理
    GPS定位基本原理
    Android Studio 之 启动和停止服务
    Android Studio 之 启动和停止服务
    【算法】最短路——两点最短总权和
    【算法】最短路——两点最短总权和
    【郑轻】[1743]解方程
    【郑轻】[1743]解方程
  • 原文地址:https://www.cnblogs.com/huang-changfan/p/10942225.html
Copyright © 2011-2022 走看看