设计模式系列:适配器模式

简介

适配器模式(Adapter Pattern)又称为变压器模式,它是一种结构型设计模式。适配器模式的目的是将一个类的接口转换成客户端所期望的另一种接口,从而使原本因接口不匹配而不能一起工作的两个类能够一起工作。

适配器模式有两种形式:类适配器(Class Adapter)和对象适配器(Object Adapter)。类适配器通过继承实现适配器功能,让Adapter实现Target接口并且继承Adaptee,这样Adapter就具备Target和Adaptee的特性,可以将两者进行转化。对象适配器通过对象组合实现适配器功能,将一个对象组合到另一个对象中,以适配其接口。

结构

适配器模式(Adapter)包含以下主要角色:

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

案例实现

类适配器

实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

【例】读卡器

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

类图如下:

代码如下:

//SD卡的接口
public interface SDCard {
    //读取SD卡方法
    String readSD();
    //写入SD卡功能
    void writeSD(String msg);
}

//SD卡实现类
public class SDCardImpl implements SDCard {
    public String readSD() {
        String msg = "sd card read a msg :hello word SD";
        return msg;
    }

    public void writeSD(String msg) {
        System.out.println("sd card write msg : " + msg);
    }
}

//电脑类
public class Computer {

    public String readSD(SDCard sdCard) {
        if(sdCard == null) {
            throw new NullPointerException("sd card null");
        }
        return sdCard.readSD();
    }
}

//TF卡接口
public interface TFCard {
    //读取TF卡方法
    String readTF();
    //写入TF卡功能
    void writeTF(String msg);
}

//TF卡实现类
public class TFCardImpl implements TFCard {

    public String readTF() {
        String msg ="tf card read msg : hello word tf card";
        return msg;
    }

    public void writeTF(String msg) {
        System.out.println("tf card write a msg : " + msg);
    }
}

//定义适配器类(SD兼容TF)
public class SDAdapterTF extends TFCardImpl implements SDCard {

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

    public void writeSD(String msg) {
        System.out.println("adapter write tf card");
        writeTF(msg);
    }
}

//测试类
public class Client {
    public static void main(String[] args) {
        Computer computer = new Computer();
        SDCard sdCard = new SDCardImpl();
        System.out.println(computer.readSD(sdCard));

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

        SDAdapterTF adapter = new SDAdapterTF();
        System.out.println(computer.readSD(adapter));
    }
}

类适配器模式违背了合成复用原则。类适配器是客户类有一个接口规范的情况下可用,反之不可用。

对象适配器模式

实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

【例】读卡器

我们使用对象适配器模式将读卡器的案例进行改写。类图如下:

在这里插入图片描述

代码如下:

类适配器模式的代码,我们只需要修改适配器类(SDAdapterTF)和测试类。

//创建适配器对象(SD兼容TF)
public class SDAdapterTF  implements SDCard {

    private TFCard tfCard;

    public SDAdapterTF(TFCard tfCard) {
        this.tfCard = tfCard;
    }

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

    public void writeSD(String msg) {
        System.out.println("adapter write tf card");
        tfCard.writeTF(msg);
    }
}

//测试类
public class Client {
    public static void main(String[] args) {
        Computer computer = new Computer();
        SDCard sdCard = new SDCardImpl();
        System.out.println(computer.readSD(sdCard));

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

        TFCard tfCard = new TFCardImpl();
        SDAdapterTF adapter = new SDAdapterTF(tfCard);
        System.out.println(computer.readSD(adapter));
    }
}

注意:还有一个适配器模式是接口适配器模式。当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可。

优缺点

适配器模式的优点包括:

  1. 扩展性:适配器模式可以用于将一个类的接口转换成客户端所期望的另一个接口,从而使得原本因接口不匹配而不能一起工作的两个类能够一起工作,这使得系统更加灵活和可扩展。
  2. 耦合度降低:通过适配器模式将不兼容的类进行适配,可以将原本耦合度较高的两个类解耦,降低系统的复杂性。
  3. 提高复用性:适配器模式可以将一个类的接口转换成客户端所期望的另一个接口,使得该类可以被更多的客户端使用,提高了代码的复用性。

然而,适配器模式也存在一些缺点:

  1. 增加中转层:适配器模式需要在原有系统基础上增加一个新的适配器层,这会增加系统的复杂性和额外的开销。
  2. 可能引入错误:由于适配器只是转换接口,而不修改原有类的实现,因此如果原有类的实现存在错误,适配器无法修正这些错误。
  3. 不易测试:由于适配器依赖于原有系统,因此对适配器的测试需要依赖于原有系统,增加了测试的难度。

应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

源码中的应用

JDK

Java I/O 库
  • 在 Java I/O 库中,有很多适配器模式的应用。比如,InputStreamReaderOutputStreamWriter 类,它们将字节流适配为字符流,允许读写字符数据而不是字节数据。这些类就充当了适配器的角色,使得不同类型的流可以通过统一的接口进行操作。
Swing GUI 组件
  • 在 Swing GUI 编程中,也有一些适配器模式的应用。例如,WindowAdapterMouseAdapterKeyAdapter 等适配器类,它们实现了对应的监听器接口,但是提供了默认的空实现,使得开发者可以选择性地实现感兴趣的事件处理方法,而不必实现所有的方法。
Arrays 类
  • JDK 中的 Arrays 类提供了很多静态方法来操作数组,其中一些方法就是适配器模式的应用。例如,asList() 方法可以将数组适配为 List 接口的实现类,这样就可以通过 List 的方式来操作数组。
java.util.Collections 类
  • Collections 类中也有一些适配器模式的应用。例如,enumeration() 方法可以将 Enumeration 适配为 Iterator,使得旧的枚举类型可以通过 Iterator 的方式进行遍历。
JDBC(Java Database Connectivity)
  • 在 JDBC 中,ResultSet 对象提供了对数据库查询结果的操作。ResultSet 接口中有一系列的 getXXX() 方法用于获取不同类型的数据,这些方法就是适配器模式的应用,将数据库中的数据适配为 Java 中的基本数据类型。

Spring

Spring MVC 中的适配器
  • 在 Spring MVC 中,HandlerAdapter 充当了适配器的角色。它负责将不同类型的处理器(handler)适配为 HandlerInterceptorHandlerExecutionChain,以便在请求处理流程中调用相应的处理器。
AOP(面向切面编程)中的适配器
  • Spring AOP 使用代理模式来实现切面(Aspect)的横切关注点。在这个过程中,适配器模式也发挥了作用。Spring AOP 通过适配器来将切面(Aspect)适配为通知(Advice),以便在目标方法调用前后或发生异常时执行相应的逻辑。
JDBC 中的适配器
  • 在 Spring 的 JDBC 模块中,JdbcAdapter 类提供了一组适配器方法,用于将不同的数据库厂商提供的 JDBC API 适配为 Spring JDBC 模板中的通用方法。这些适配器方法使得开发者可以以统一的方式访问不同数据库的数据。
消息队列中的适配器
  • 在 Spring Integration 框架中,适配器模式也被广泛应用。例如,MessageAdapter 用于将消息适配为 Spring Integration 中的消息类型,从而与 Spring Integration 的通道和端点进行交互。
测试模块中的适配器
  • 在 Spring Test 模块中,提供了一系列的适配器类,用于将不同的测试框架适配为 Spring Test 上下文中可用的测试类。例如,TestContextManager 适配了 JUnit 和 TestNG 测试框架,使得它们能够在 Spring 测试上下文中进行集成测试。

.Net Core

接口适配器
  • 接口适配器是指适配器类实现了一个接口,并将该接口的方法委托给另一个类的实例。在 .NET Core 中,这种模式常见于接口的默认实现。
  • 例如,在 .NET Core 中的 ASP.NET Core 框架中,IActionResult 接口定义了一种返回结果的标准,而 ActionResult 类则是这个接口的适配器,提供了接口方法的默认实现。
public interface IActionResult
{
    Task ExecuteResultAsync(ActionContext context);
}

public class ActionResult : IActionResult
{
    public virtual Task ExecuteResultAsync(ActionContext context)
    {
        // 提供了接口方法的默认实现
        return Task.CompletedTask;
    }
}
类适配器
  • 类适配器是指适配器类继承了另一个类,并实现了一个接口。在 .NET Core 中,类适配器常见于需要同时继承某个基类并实现某个接口的情况。
  • 例如,Entity Framework Core 中的数据库上下文(DbContext)就是一个类适配器,继承自 DbContextBase 并实现了 IDbContext 接口。
public class DbContext : DbContextBase, IDbContext
{
    // 实现接口方法
    public void SaveChanges()
    {
        // ...
    }
}
对象适配器
  • 对象适配器是指适配器类持有另一个类的实例,并实现一个接口。在 .NET Core 中,对象适配器常见于需要通过组合而非继承来实现适配的情况。
  • 例如,在 .NET Core 中的 HttpClient 类可以被视为一个对象适配器,它持有一个 HttpMessageHandler 实例,并实现了 IDisposable 接口。
public class HttpClient : IDisposable
{
    private readonly HttpMessageHandler _handler;

    public HttpClient(HttpMessageHandler handler)
    {
        _handler = handler;
    }

    // 实现接口方法
    public void Dispose()
    {
        _handler.Dispose();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/557205.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

润开鸿与蚂蚁数科达成战略合作,发布基于鸿蒙的mPaaS移动应用开发产品

4月18日,江苏润和软件股份有限公司(以下简称“润和软件”) 旗下专注鸿蒙方向的专业技术公司及终端操作系统发行版厂商江苏润开鸿数字科技有限公司(以下简称“润开鸿”)与蚂蚁数科举行战略合作签约仪式,并发…

腾讯后端一面:当 TCP 建立连接之后,TCP 和 UDP 的实时性是不是就差不多了?

更多大厂面试内容可见 -> http://11come.cn 腾讯后端一面:当 TCP 建立连接之后,TCP 和 UDP 的实时性是不是就差不多了? 项目相关 面试官可能是 Go 方向的,我面试的是 Java 方向的,所以面试官也没有问我简历上的项…

Uniswap丨justswap丨pancakeswap去中心化薄饼交易所系统开发

开发去中心化薄饼交易所系统(如Uniswap、JustSwap、PancakeSwap)是一个复杂而有挑战性的任务,需要综合考虑技术、安全、用户体验和合规等方面。以下是开发这样一个系统时需要考虑的关键方面: 1. 技术架构 智能合约开发&#xff1…

【智能算法】鸡群优化算法(CSO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2014年,X Meng等人受到鸡群社会行为启发,提出了鸡群优化算法(Chicken Swarm Optimization, CSO)。 2.算法原理 2.1算法思想 CSO算法的思想是基于对…

RIP小实验配置及缺省路由下发

配置如下: IP配置: IP配置完先查看RIP协议学习到的路由表,没有内容则代表没有开启RIP 启用RIP:这里的rip后跟的ID只具有本地意义,可以在1-65535之间随便取,不同路由器之间都可以取用不同的,为了…

PHP 基础

初识PHP 了解PHP 语言 PHP 语言标记 <h1>My Name is 123!</h1> <script>console.log("This message is from info.php!") </script> <?php // PHP 的开始标记&#xff0c;表示从此标记开始&#xff0c;进入PHP 模式。phpin…

SpringBoot 项目Docker部署三种方式

一种&#xff1a;直接拷贝jar到服务器部署 1.增加docker配置文件 新建Dockerfile文件&#xff0c;负责Docker的配置 FROM openjdk:21#ENV timezone RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \&& echo Asia/Shanghai >/etc/timezone# WORKD…

TCP和UDP协议的区别

1、定义 TCP协议的全称是Transmission Control Protocol&#xff08;传输控制协议&#xff09;&#xff0c;是一种面向连接的点对点的传输层协议。 UDP协议的全称是User Datagram Protocal&#xff08;用户数据报协议&#xff09;&#xff0c;为应用程序提供一种无需建立连接…

OpenHarmony音频和音乐编码格式—vorbis

简介 一种通用音频和音乐编码格式。 Vorbis编解码器规范属于公共领域。所有技术细节都已发布并记录&#xff0c;任何软件实体都可以充分利用该格式&#xff0c;而无需支付许可费、版税或专利问题。 下载安装 直接在OpenHarmony-SIG仓中搜索vorbis并下载。 使用说明 以OpenHa…

Qt6之QScopedPointer——智能指针

手动管理堆分配的对象困难且容易出错&#xff0c;当指针场景复杂时&#xff0c;手动delete难免出错&#xff0c;常见的结果是代码泄漏内存并且难以维护。是时候使用现代和安全的一些方法了&#xff0c;那就是使用智能指针&#xff0c;比如 QScopedPointer 或 std::unique_ptr&a…

idea新建一个springboot项目

本文分为几个部分&#xff0c; 首先是在idea中新建项目&#xff0c; 然后是配置 项目的目录&#xff08;新建controller、service、dao等&#xff09;&#xff0c; 然后是自定义的一些工具类&#xff08;比如启动后打印地址等&#xff09;。 1.、创建篇 新建项目&#xff0…

分享|视频号带货如何运营才能实现盈利?

在当今数字化时代&#xff0c;视频号带货已经不仅仅是一种商业手段&#xff0c;更是一种生活方式和社交体验。运营视频号带货并实现盈利&#xff0c;需要我们从多个角度进行深入思考和创新实践。 首先&#xff0c;从用户体验的角度出发 我们需要关注观众的观看体验和购物体验。…

游戏登录界面制作

登录界面制作 1.导入模块和初始化窗口 import subprocessimport tkinter as tkimport picklefrom tkinter import messageboxwindow tk.Tk()window.title(Welcome)window.geometry(450x300) 导入必要的模块&#xff0c;并初始化了主窗口window&#xff0c;设置了窗口的标题和…

STM32完成软件I2C通讯

今天的重点是利用STM32的软件方案和MPU60506轴姿态传感器建立通讯&#xff0c;今天只完成了简单的发送地址和接收应答的部分&#xff0c;特此记录一下过程&#xff0c;以后忘记可以随时翻出来看看。 先介绍最基本的I2C通讯的最基本的6个时序&#xff1a; 一&#xff1a;起始条…

【Yolov系列】Yolov5学习(一)补充2:自适应锚框计算详解+代码注释

一、自适应锚框计算详解 自适应锚框计算的具体过程&#xff1a; ①获取数据集中所有目标的宽和高。 ②将每张图片中按照等比例缩放的方式到 resize 指定大小&#xff0c;这里保证宽高中的最大值符合指定大小。 ③将 bboxes 从相对坐标改成绝对坐标&#xff0c;这里…

预印本仓库ArXiv——防止论文录用前被别人剽窃

文章目录 一、什么是预印本二、什么是ArXiv2.1 ArXiv的领域2.2 如何使用 一、什么是预印本 预印本&#xff08;Preprint&#xff09;是指科研工作者的研究成果还未在正式出版物上发表&#xff0c;而出于和同行交流目的自愿先在学术会议上或通过互联网发布的科研论文、科技报告…

SQL Server 2022 安装及使用

SQL Server 2022 前言一、安装SQL Server 2022下载SQL Server 2022安装SQL Server 2022配置SQL Server 2022 二、安装SQL Server Management Studio下载SQL Server Management Studio安装SSMS-Setup-CHS 三、使用SQL Server 2022四、解决连接到服务器报错问题 前言 SQL Serve…

轻松get!分享4种关于iPhone通话记录怎么查询的方法

想要轻松了解你的iPhone通话记录&#xff1f;通话记录怎么查询&#xff1f;不用担心&#xff0c;我们在这篇文章中将分享四种简单有效的方法&#xff0c;帮助你查询iPhone上的通话记录。 无论是查看最近的通话记录还是检索特定日期范围内的通话历史&#xff0c;这些方法都能帮…

AI:162-如何使用Python进行图像识别与处理深度学习与卷积神经网络的应用

本文收录于专栏&#xff1a;精通AI实战千例专栏合集 从基础到实践&#xff0c;深入学习。无论你是初学者还是经验丰富的老手&#xff0c;对于本专栏案例和项目实践都有参考学习意义。 每一个案例都附带关键代码&#xff0c;详细讲解供大家学习&#xff0c;希望可以帮到大家。正…

AI大模型日报#0418:Stable Diffusion 3开放API、Meta新研究让AI Agent理解物理世界

导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。标题: 微软刚发布了VASA-1 这个人工智能可以让单张图像具有生动的说话和歌唱能力 摘要: 微软发布了VASA-1人工智能&#xff0c;它能使单…
最新文章