【JAVA设计模式】适配器模式——类适配器模式详解与案例分析

前言

在软件设计中,适配器模式(Adapter Pattern)是一种结构型设计模式,旨在使不兼容的接口能够协同工作。它通过引入一个适配器类,帮助两个接口之间进行适配,使得它们能够互相操作。本文将详细介绍适配器模式的定义、使用场景、实现方式、接口适配器以及其优缺点。

一、适配器模式的定义

适配器模式通过引入一个适配器类,将一个类的接口转换成客户端所期望的另一种接口。适配器模式的核心在于"适配",它允许原本由于接口不兼容而无法一起工作的类能够协同工作。

主要角色

  1. 目标接口(Target):目标接口是客户端所期望的接口,定义了客户端需要的方法。客户端代码依赖于目标接口而不是具体的实现类,这样可以使系统更加灵活和可扩展。
  2. 适配者类(Adaptee):源接口是现有的接口,它的接口与目标接口不一致。源接口包含了客户端需要的实际功能,但其接口形式无法直接被客户端使用。
  3. 适配器类(Adapter):适配器实现目标接口,并持有源接口的实例(对象适配器)或继承源接口(类适配器)。适配器通过在实现目标接口的方法中调用源接口的方法,将源接口的方法转换成目标接口的方法。

三者之间的关系

  • 客户端依赖目标接口进行编程。
  • 适配器实现了目标接口,并通过组合或继承的方式调用源接口的方法。
  • 适配器将源接口的方法适配成目标接口的方法,从而使得客户端可以无缝地使用源接口的功能。

二、适配器模式的使用场景

适配器模式适用于以下情况:

  1. 系统需要使用现有的类,但接口不符合要求:如果你有一个类,它的接口与系统的需求不匹配,可以通过适配器模式进行转换。
  2. 需要使用多个现有的类,但接口不一致:如果系统中需要整合多个不兼容的接口,可以通过适配器模式使其兼容。
  3. 系统中使用第三方库或框架:当你引入第三方库或框架时,可能会遇到接口不一致的情况,适配器模式可以帮助解决这些问题。

三、适配器模式的实现方式

适配器模式有三种主要的实现方式:类适配器,对象适配器和接口适配器

本文讲解的是类适配器

类适配器

特点

  • 使用继承:类适配器通过继承源类来实现适配功能。

  • 单一适配:由于 Java 中不支持多重继承,类适配器只能适配一个源类。

优缺点

优点
  1. 简单实现
    • 由于类适配器通过继承实现,它可以直接访问被适配类(Adaptee)的所有方法。这使得实现适配器时相对简单,不需要额外的委托逻辑。
  2. 提高代码的可复用性
    • 适配器模式通过继承实现,使得子类能够继承父类的所有功能,从而提高了代码的复用性。
  3. 可以重定义被适配类的一些行为
    • 通过继承,可以在适配器类中重定义被适配类的一些方法,实现更加灵活的适配。
缺点
  1. 受限于单继承
    • 类适配器模式在Java等单继承语言中有一个显著的缺点,即一个类只能继承一个父类。这意味着如果适配器类已经有一个父类,就不能再使用类适配器模式来继承另一个类。
  2. 高耦合
    • 适配器类和被适配类之间的耦合度较高,因为适配器类直接继承了被适配类的实现。如果被适配类发生变化,适配器类可能也需要进行相应的修改。
  3. 不符合"组合优于继承"原则
    • 面向对象设计中,组合优于继承的原则提倡使用组合来代替继承,以降低类之间的耦合度。类适配器模式违背了这一原则,因为它是通过继承来实现适配的。

【例】读卡器

现有一台电脑只能读取SD卡,而要读取TE卡中的内容的话就需要使用到适配器模式。创建一个读卡器,将IE卡中的内容读取出来。

类图如下:

其中:

为适配者类

定义了一个接口 TFCard 接口,有两个方法(读取数据,写数据)。子实现类TFCardImpl重写了接口的两个方法

这一部分为目标接口,主要是SDCard(包含两个方法:读数据,写数据),子实现类为SDcardImpl

Computer只能使用SD卡,所以方法名为readSD(),需要SDcard类型的对象,返回字符串

当我们想用Computer去读取TF卡中的内容,不能直接读取,需要定义适配器类:

我们要让这个适配器类实现目标接口,就要重写SDCard中的两个方法,同时我们要让它去继承TFCardImpl

实现之后这两个方法看似是从SD卡中读数据写数据,但是实际上用的是TF卡中的功能

代码实现

java 复制代码
//客户端
public class Client {
    public static void main(String[] args) {
        //创建计算机对象
        Computer computer = new Computer();
        //读取SD卡中的数据
        String msg = computer.readSD(new SDCardImpl());
        System.out.println(msg);

        System.out.println("==============================");

        //使用该电脑读取TF卡中的数据
        //定义适配器类
        String msg1 = computer.readSD(new SDAdapterTF());
        System.out.println(msg1);
    }
}
java 复制代码
//计算机类
public class Computer {

    //从SD卡中读取数据
    public String readSD(SDCard sdCard) {
        if (sdCard == null) {
            throw new NullPointerException("sd card is null");
        }
        return sdCard.readSD();
    }
}
java 复制代码
//适配器类
public class SDAdapterTF extends TFCardImpl implements SDCard {

    @Override
    public String readSD() {
        System.out.println("adapter read tf card");
        return readTF();
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("adapter wrete tf card");
        writeTF(msg);
    }
}
java 复制代码
public interface SDCard {

    //从SD卡中读取数据
    String readSD();
    //往SD卡中写数据
    void writeSD(String msg);
}
java 复制代码
//具体的SD卡
public class SDCardImpl implements SDCard{
    @Override
    public String readSD() {
        String msg = "SDCard read msg : SD";
        return msg;
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("SDCard write msg : " + msg);
    }
}
java 复制代码
//适配者类的接口
public interface TFCard {

    //从TF卡中读取数据
    String readTF();

    //往TF卡中写数据
    void writeTF(String msg);

}
java 复制代码
//适配者类
public class TFCardImpl implements TFCard{

    @Override
    public String readTF() {
        String msg = "TFCard read msg : TF";
        return msg;
    }

    @Override
    public void writeTF(String msg) {
        System.out.println("TFCard write msg : " + msg);
    }
}

四、总结

适配器模式是一种强大的设计模式,能够有效解决接口不兼容的问题,使得不同接口的类能够协同工作。通过合理使用适配器模式,可以提高系统的灵活性和复用性,但也需要注意其可能带来的复杂性和性能影响。

希望本文对你理解适配器模式有所帮助。如果你有任何问题或建议,欢迎在评论区留言!


参考资料:12.设计模式-结构型模式-类适配器模式案例实现_哔哩哔哩_bilibili

已经到底啦!!

相关推荐
维天说2 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19943 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
杨充4 小时前
11.DDD与战术建模
设计模式·开源·代码规范
杨充4 小时前
12.综合实战图片框架
设计模式·开源·代码规范
噢,我明白了4 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品4 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘4 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记4 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端
糖果店的幽灵5 小时前
langgraph的 MessagesState 解读
java·开发语言·人工智能·windows·langgraph
极光代码工作室6 小时前
基于SpringBoot的在线博客系统
java·springboot·web开发·后端开发