Java设计模式 _结构型模式_适配器模式

一、适配器模式

**1、适配器模式(Adapter Pattern)**是一种结构型设计模式。适配器类用来作为两个不兼容的接口之间的桥梁,使得原本不兼容而不能一起工作的那些类可以一起工作。譬如:读卡器就是内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取或写入数据到内存卡。

2、实现思路

总的来说:实现业务类注入适配器中,适配器注入调用类中。调用类使用适配器的方法,适配器使用实现业务类的方法。

具体步骤如下:

(1)、创建适配器类(Adapter),实现和业务类(Computer)相同的功能接口(Abilities)

(2)、适配器类注入功能接口(Abilities)的属性类。重写构造方法,根据传入或其他参数实例化这个属性类

(3)、适配器类实现功能接口(Abilities)的抽象方法,通过自身的属性类去实现调用。

(4)、在业务类(Computer)中,注入适配器类(Adapter)的属性类,重写构造方法实例化适配器。

(5)、在业务类中,使用适配器的实现方法替换原本自身的实现方法。

二、代码示例

1、示例1

电脑(Computer),内存卡(MemoryCard),读卡器(ReadCardAdapter)。电脑通过读卡器完成对内存卡数据的读取和写入。

代码示例:

java 复制代码
// 定义规范超类,读取数据,写入数据的接口
public interface Abilities {
    // 读取数据
    public void readData();
    // 存储数据
    public void storeData();
}
// 定义内存卡类
public class MemoryCard implements Abilities{
    @Override
    public void readData() {
        System.out.println("读取了内存卡数据");
    }
    @Override
    public void storeData() {
        System.out.println("数据存储到内存卡");
    }
}
// 定义适配器类,需要实例具体的业务类
public class CardReaderAdapter implements Abilities {
    private MemoryCard memoryCard;
    public CardReaderAdapter(MemoryCard memoryCard){
        this.memoryCard = memoryCard;
    }
    @Override
    public void readData() {
        memoryCard.readData();
    }
    @Override
    public void storeData() {
        memoryCard.storeData();
    }
}
// 定义电脑类,注入适配器类
public class Computer implements Abilities{
    private CardReaderAdapter cardReaderAdapter;
    public Computer(CardReaderAdapter cardReaderAdapter){
        this.cardReaderAdapter =cardReaderAdapter;
    }
    @Override
    public void readData() {
        cardReaderAdapter.readData();
    }
    @Override
    public void storeData() {
        cardReaderAdapter.storeData();
    }
}
// 测试
public class Ztest {
    public static void main(String[] args) {
        MemoryCard memoryCard = new MemoryCard();
        CardReaderAdapter adapter = new CardReaderAdapter(memoryCard);
        Computer computer = new Computer(adapter);
        computer.readData();
        computer.storeData();
    }
}

运行结果:

上图可以看出,虽然实现的是电脑的实例对象,调用的确实内存卡的业务实现方法。说明适配器生效了。

2、示例2

原本的音频播放器(AudioPlayer),仅支持播放mp3,现在需要扩展播放wav格式和pcm格式的文件
最初代码示例:

java 复制代码
// 定义规范超类,播放文件的接口
public interface Abilities {
    void play(String name);
}
// 定义音频播放器类,播放mp3文件
public class AudioPlayer implements Abilities {
    @Override
    public void play( String name) {
        String type = name.substring(name.indexOf(".")+1);
        if ("mp3".equals(type)) {
            System.out.println("原生播放器播放:" + name);
        } else {
            System.out.println("不支持的格式!");
        }
    }
}
// 测试
public class Ztest {
    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();
        audioPlayer.play("青花瓷.mp3");
        audioPlayer.play("鸟语花香.wav");
    }
}

运行结果

可以看到目前仅支持播放mp3的文件,其他格式不支持播放。

改造思路:

编写扩展的实例类,通过注入适配器,将适配器注入原始类的方法,实现原始类可以调用自身方法或者适配器方法的多种情形。

使用适配器修改后,代码示例如下:

java 复制代码
// 定义规范超类,播放文件的接口
public interface Abilities {
    void play(String name);
}
// 创建播放wav格式的实例类,实现超类
public class WavPlayer implements Abilities {
    @Override
    public void play(String name) {
        System.out.println("Wav播放器播放:" + name);
    }
}
// 创建播放pcm格式的实例类,实现超类
public class PcmPlayer implements Abilities {
    @Override
    public void play(String name) {
        System.out.println("Pcm播放器播放:" + name);
    }

}
// 创建适配器类,根据业务场景注入超类的实例,调用注入实例的实现方法
public class AudioAdapter implements Abilities {
    private Abilities abilitiesPlay;

    public AudioAdapter(String type) {
        if ("wav".equals(type)) {
            this.abilitiesPlay = new WavPlayer();
        } else if ("pcm".equals(type)) {
            this.abilitiesPlay = new PcmPlayer();
        }
    }

    @Override
    public void play(String name) {
        abilitiesPlay.play(name);
    }
}
// 修改音频播放器,注入适配器,根据条件选择调用原生方法或者适配器的方法
public class AudioPlayer implements Abilities {
    private AudioAdapter audioAdapter;
    
    @Override
    public void play(String name) {
        String type = name.substring(name.indexOf(".") + 1);
        if ("mp3".equals(type)) {
            System.out.println("原生播放器播放:" + name);
        } else if ("wav".equals(type) || "pcm".equals(type)) {
            audioAdapter = new AudioAdapter(type);
            audioAdapter.play(name);
        } else {
            System.out.println("不支持的格式!");
        }
    }
}
// 测试
public class Ztest {
    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();
        audioPlayer.play("青花瓷.mp3");
        audioPlayer.play("青鸟.wav");
        audioPlayer.play("鼓风机采集声音.pcm");
        audioPlayer.play("鸟语花香.avi");
    }
}

运行结果:

上图可以看到已经支持播放了两种新的格式的文件。

学海无涯苦作舟!!!

相关推荐
FF在路上17 分钟前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进24 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
众拾达人1 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.1 小时前
Mybatis-Plus
java·开发语言
不良人天码星1 小时前
lombok插件不生效
java·开发语言·intellij-idea
守护者1701 小时前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
源码哥_博纳软云1 小时前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
禾高网络1 小时前
租赁小程序成品|租赁系统搭建核心功能
java·人工智能·小程序
学会沉淀。1 小时前
Docker学习
java·开发语言·学习
如若1231 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python