当前位置: 首页 > news >正文

深入理解设计模式-结构型之适配器

适配器模式(Adapter Pattern):

适配器模式用于将一个类的接口转换成另一个类的接口,以使两者能够一起工作。适配器模式通常用于处理已经存在的类让它们能够与其他类协同工作而不需要修改原始类的代码。(用于解决两个不兼容接口之间的问题。适配器允许将一个类的接口转换为客户端期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。)

主要组成部分:

  • 目标接口(Target Interface):定义客户端期望的接口。

  • 适配者(Adaptee):已经存在的类,需要被适配以满足目标接口。

  • 适配器(Adapter):实现目标接口,并在内部持有一个适配者对象,将目标接口方法调用转发给适配者。

    • 适配者(Adaptee)是一个已经存在的类,它实现的是在早期已经定义好的接口,而这个接口与你的系统中要求的目标接口(也就是客户端所期望的接口)不兼容。
    • 适配者的接口可能是一个旧的、第三方的、或者是不同版本的接口。这个接口可能已经在一些已有的类中得到了实现,但它的方法名、参数或者行为与你的系统中的目标接口不匹配。
    • 所以,为了能够在你的系统中使用这个已经存在的类,你需要创建一个适配器来将这个已有的接口适配到你的目标接口上。

适配器模式的核心思想就是通过适配器类,将适配者的接口适配成符合你的系统需求的目标接口,从而能够让这个已经存在的类能够被无缝地集成到你的系统中。

适配器模式示例:

假设有一个旧系统中的类 OldSystem,它有一个方法 oldMethod。现在我们想在新系统中使用这个方法,但新系统要求使用一个新的接口 NewInterface。

适配器模式有两种实现方式:类适配器和对象适配器。

  • 对象适配器:
    • 对象适配器使用组合来实现适配器功能。适配器类包含一个原有类的实例。
// 旧系统的类(适配者 adaptee)
class OldSystem {void oldMethod() {System.out.println("Old System Method");}
}// 新系统的接口
interface NewInterface {void newMethod();
}// 适配器类
class Adapter implements NewInterface {private OldSystem oldSystem; //适配器类包含一个原有类的实例。//构造注入public Adapter(OldSystem oldSystem) {this.oldSystem = oldSystem;}public void newMethod() {oldSystem.oldMethod();}
}// 客户端代码
public class AdapterExample {public static void main(String[] args) {OldSystem oldSystem = new OldSystem();NewInterface adapter = new Adapter(oldSystem);adapter.newMethod(); // 调用旧系统的方法,通过适配器实现新接口}
}
  • 类适配器:
    • 类适配器使用继承来实现适配器功能。适配器类继承了原有的类(Adaptee)并实现了目标接口(Target)
//适配者(旧)和接口和上面一样。
// 适配器类
class Adapter extends OldSystem implements NewInterface {public  void newMethod(){oldMethod();}
}// 客户端代码
public class AdapterExample {public static void main(String[] args) {NewInterface adapter = new Adapter();adapter.newMethod(); // 调用旧系统的方法,通过适配器实现新接口}
}

适配器类的作用是将已存在的接口适配到另一个不兼容的接口上,使得客户端代码能够通过目标接口与适配者进行交互。

应用场景

  • 集成旧系统或第三方库:当你需要使用一个已经存在的类或库,但其接口与你当前系统的其他部分不兼容时,适配器模式可以帮助你将这个类适配为符合你系统需求的接口。

  • 接口版本升级:当接口的一个新版本发布,但你的系统还在使用旧版本接口时,通过适配器模式可以兼容旧版本接口,同时适配到新版本接口上。

  • 多接口转换:当一个类需要实现多个接口,但这些接口的方法命名、参数或行为存在冲突时,可以使用适配器模式来适配这些接口,使它们能够被同一个类实现。

  • 现有类不符合需要的接口:有时你可能需要一个类来实现某个接口,但这个类并没有实现该接口。通过创建适配器类,你可以将这个类的方法适配到接口的方法上,使得类能够满足接口的要求。

  • 接口的多态性:适配器模式可以帮助你在多态性的情境中使用不同的实现,以适应不同的场景。

适配器模式的主要用途是在不改变现有类的情况下,让原本不兼容的接口能够协同工作。这在软件开发中常常遇到,特别是在集成不同模块、版本升级、对外提供兼容接口等情况下非常有用。

源码应用

  • Java IO:InputStreamReader 和 OutputStreamWriter 类将字节流适配为字符流,实现了字符流与字节流之间的适配。

  • org.springframework.web.servlet.HandlerAdapter 接口是 Spring MVC 框架中的一个关键接口,**用于将不同类型的处理器(例如控制器)适配为统一的处理方式,**以便处理请求。不同的处理器可能需要不同的适配逻辑,因此 Spring 提供了多个实现类来适应不同的处理器类型。

    • RequestMappingHandlerAdapter:这是 Spring MVC 默认使用的适配器,用于适配使用注解 @RequestMapping 的控制器方法。它支持将方法返回的数据适配为视图或其他形式。
    • WebSocketHandlerAdapter:用于适配实现了 WebSocketHandler 接口的处理器,用于处理 WebSocket 请求。
    • SimpleServletHandlerAdapter:用于适配实现了 Servlet 接口的处理器,允许你将一个 Servlet 类适配为 Spring MVC 的处理器。

这些适配器实现了相应的适配逻辑,将不同类型的处理器适配为统一的处理方式,以满足 Spring MVC 的框架要求。通过这些适配器,Spring MVC 可以在处理不同类型的请求时统一调用适当的处理器,并将处理结果适配为视图或其他响应形式。

相关文章:

深入理解设计模式-结构型之适配器

适配器模式(Adapter Pattern): 适配器模式用于将一个类的接口转换成另一个类的接口,以使两者能够一起工作。适配器模式通常用于处理已经存在的类,让它们能够与其他类协同工作,而不需要修改原始类的代码。&…...

桥梁结构健康监测系统,智能预警降低桥梁安全隐患

桥梁通常位于现代综合交通网络中的咽喉部位,对区域经济发展起着重要的推进作用,然而在为社会经济发展做出巨大贡献的同时,它们不可避免地会在荷载作用、环境侵蚀和自然灾害等影响下出现材料腐蚀劣化、结构损伤开裂、性能退化和功能失效等损伤…...

夏威夷等全球多地深陷「末日狂烧」,关键时刻 AI 监测能否跑赢野火?

内容一览:当地时间 8 月 8 日,美国夏威夷州突发野火,当地居民和游客不得不跳入太平洋中躲避火势。截至 8 月 17 日,这场野火已经造成110 人死亡,超过 1000人失踪。与此同时,美国、加拿大、法国等地也正遭遇…...

解决多模块内核心模块有接口打包成jar后被依赖并调用遇到的问题(springcloud集成ruoyi.quartz)

项目准备开发个新功能,刚好很喜欢ruoyi写的任务调度,因此想到了集成ruoyi.quartz模块 ,遇到了很多问题: 首先因为ruoyi.quartz模块依赖了ruoyi.common模块,因此第一步我需要把common模块一部分依赖项复制到了quartz模块内&#xf…...

【kubernetes系列】Kubernetes之Kubelet运行机制和状态更新机制

Kubelet运行机制 Kubelet是Kubernetes中的一个重要组件,在每个 Node 节点上都会启动 kubelet 服务。 该服务主要用于处理 Master 节点下发到本节点的任务,管理 Pod及Pod 中的容器。每个kubelet 进程会在 API Server 上注册节点自身信息,定期…...

(学习笔记-进程管理)怎么避免死锁?

死锁的概念 在多线程编程中,我们为了防止多线程竞争共享资源而导致数据错乱,都会在操作共享资源之前加上互斥锁,只有成功获得到锁的线程,才能操作共享资源,获取不到锁的线程就只能等待,直到锁被释放。 那…...

【golang】链表(List)

List实现了一个双向链表,而Element则代表了链表中元素的结构。 可以把自己生成的Element类型值传给链表吗? 首先来看List的四种方法。 MoveBefore方法和MoveAfter方法,它们分别用于把给定的元素移动到另一个元素的前面和后面。 MoveToFro…...

android平台的语音聊天助手源码

目录 1 android平台的语音聊天助手源码 1.1 //js处理工具类 1.1.1 openImage 1.2 LoadWebDetails android平台的语音聊天助手源码package com.shrimp.xiaoweirobot.net; import java.util.ArrayList;...

Python读取Word统计词频输出到Excel

1.安装依赖的包 "# 读取docx\n", "!pip install python-docx\n", "!pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-docx\n", "# 中英文分词\n", "!pip install jieba\n", "!pi…...

windows docker mysql8.0 挂载配置文件不生效的问题

原因 mysql 8.0 遇到sql_modeonly_full_group_by的问题,于是就自定义my.cnf 去掉only_full_group_by,修改my.cnf 文件后,进行映射启动 docker run 命令 docker run -p 3306:3306 --privilegedtrue --restartalways -d --name axsc-mysql -…...

openGauss学习笔记-42 openGauss 高级数据管理-触发器

文章目录 openGauss学习笔记-42 openGauss 高级数据管理-触发器42.1 语法格式42.2 参数说明42.3 示例 openGauss学习笔记-42 openGauss 高级数据管理-触发器 触发器会在指定的数据库事件发生时自动执行函数。 42.1 语法格式 创建触发器 CREATE TRIGGER trigger_name { BEFORE…...

Leetcode33 搜索旋转排序数组

题解: /*** 旋转排序数组可分为N1 N2两个部分,如:[4,5,6,7,1,2,3],N1为[4,5,6,7],N2为[1,2,3]** 必然满足以下两个条件:* 1. N1和N2都是分别递增的;* 2. N1中的所有元素大于N2中的所有元素;** …...

docker 第一章

目录 1.安装 docker 2.镜像、容器 3.总结 1.安装 docker 2.镜像、容器 3.总结 容器在 linux 上的本机运行,与其他容器共享主机的内核。它运行的是一个独立的进程,不占用其他任何可执行文件的内存,非常轻量级。...

注册中心 —— SpringCloud Netflix Eureka

Eureka 简介 Eureka 是一个基于 REST 的服务发现组件,SpringCloud 将它集成在其子项目 spring-cloud-netflix 中,以实现 SpringCloud 的服务注册与发现,同时提供了负载均衡、故障转移等能力,目前 Eureka2.0 已经不再维护&#xf…...

2023年国赛数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...

⛳ Java 反射

目录 ⛳ Java 反射🎨 一、反射概述**🎃 使用反射的前提条件: **🎲 类正常加载过程如下图:反射优缺点:🧸 Java反射机制提供的功能: **🥅 反射主要API** 🏭 二、反射的使用&#x1f3a…...

Android 13 像Settings一样开启关闭深色模式

一.背景 由于客户定制的Settings需要开启关闭深色模式,所以需要自己调用开启关闭深色模式 二.前提条件 首先应用肯定要是系统应用,并且导入framework.jar包,具体可以参考: Android 应用自动开启辅助(无障碍)功能并使用辅助(无障碍)功能_android 自动开启无障碍服务_龚礼鹏…...

微服务实战项目-学成在线-项目优化(redis缓存优化)

微服务实战项目-学成在线-项目优化(redis缓存优化) 1 优化需求 视频播放页面用户未登录也可以访问,当用户观看试学课程时需要请求服务端查询数据,接口如下: 1、根据课程id查询课程信息。 2、根据文件id查询视频信息。 这些接口在用户未认…...

IDEA 找不到项目 ‘org.springframework.boot:spring-boot-starter-parent:3.1.2‘

找不到项目 ‘org.springframework.boot:spring-boot-starter-parent:2.6.7’ 这个问题主要是因为ide的缓存导致的,我们直接清理缓存并重启ide 重启之后ide会对pom文件进行编排索引完成之后问题就没有了...

thinkphp开发的在线学习培训考试模拟考试做题练习系统带商城功能证书管理课程系统

thinkphp开发的在线学习培训考试模拟考试做题练习系统带商城功能证书管理课程系统 1、做题界面 2、前端UI的展示 3、带商城购物功能...

终极OBS Studio直播软件指南:5步打造专业级智能直播系统

终极OBS Studio直播软件指南:5步打造专业级智能直播系统 【免费下载链接】obs-studio OBS Studio - 用于直播和屏幕录制的免费开源软件。 项目地址: https://gitcode.com/GitHub_Trending/ob/obs-studio 想象一下这样的场景:你正在直播一场重要的…...

OpenClaw 的模型服务是否支持限流和熔断?策略如何配置?

在讨论OpenClaw模型服务的限流与熔断机制之前,不妨先回想一下城市交通系统。早晚高峰时,交警会在关键路口设置信号灯或临时管制,防止车辆过度涌入导致整个区域瘫痪。模型服务面临的场景其实非常相似——外部请求就像不断驶入的车辆&#xff0…...

threejs 加载glb模型时DRACOLoader的正确配置与常见错误解析

1. 为什么需要DRACOLoader? 在Three.js中加载glb/gltf模型时,经常会遇到模型文件过大的问题。这是因为很多3D建模工具(如Blender)在导出时会使用Draco压缩算法来减小文件体积。这种压缩虽然能显著减少模型大小(通常能…...

Mod5实战:从零构建大气辐射传输模拟与辐照度计算全流程

1. 从零开始:为什么需要大气辐射传输模拟? 第一次接触大气辐射传输模拟的朋友可能会问:这玩意儿到底有什么用?简单来说,就像给地球大气层做CT扫描。我在做光伏电站选址评估时,就深刻体会到它的价值——通过…...

对于对话中的反讽识别,OpenClaw 的模型是否结合了语调特征?

关于OpenClaw模型在反讽识别中是否结合了语调特征,这个问题其实触及了当前自然语言处理中一个相当微妙的领域。从技术实现的角度来看,OpenClaw这类基于Transformer架构的大语言模型,其训练数据主要来源于互联网上的文本语料,比如网…...

PyTorch训练二分类模型时,你的损失函数为什么突然变成NaN了?排查BCELoss的5个坑

PyTorch训练二分类模型时,你的损失函数为什么突然变成NaN了?排查BCELoss的5个坑 深夜的调试台前,咖啡杯早已见底,屏幕上那个刺眼的"nan"却依然顽固地停留在损失值的位置。这不是第一次,也不会是最后一次——…...

LibreTranslate模型部署优化指南:从技术痛点到落地实践

LibreTranslate模型部署优化指南:从技术痛点到落地实践 【免费下载链接】LibreTranslate Free and Open Source Machine Translation API. Self-hosted, offline capable and easy to setup. 项目地址: https://gitcode.com/GitHub_Trending/li/LibreTranslate …...

3大核心功能打造专业级开源服装设计解决方案

3大核心功能打造专业级开源服装设计解决方案 【免费下载链接】Seamly2D Open source patternmaking software to democratize fashion. 项目地址: https://gitcode.com/gh_mirrors/se/Seamly2D Seamly2D作为一款开源服装制版软件,通过参数化设计、精确测量管…...

别再死记硬背了!用5分钟搞懂NPN和PNP三极管的电流流向(附快速判断技巧)

5分钟掌握NPN与PNP三极管的电流奥秘:从生活场景到实战技巧 记得第一次拆解收音机时,那些黑色的小方块上延伸出的金属腿让我一头雾水——它们看起来平平无奇,却能控制电流的放大与开关。直到导师用浇花的水管作比喻,三极管的秘密才…...

Linux下安装SimSun字体的完整指南(附常见问题排查)

Linux下安装SimSun字体的完整指南(附常见问题排查) 在Linux系统中处理中文字体一直是个让开发者头疼的问题。不同于Windows系统预装了丰富的中文字体,大多数Linux发行版默认只包含基础的字体库。当我们需要处理中文文档、开发中文界面或运行某…...