实用的设计模式08——适配器模式

适配器的单词是Adapter,我们在开发时经常碰到叫做XxxAdapter的类,此时一般就是使用了适配器模式,适配器模式是非常常用,本文就对适配器模式做一个简单的介绍

文章目录

  • 1、真实开发场景的问题引入
  • 2、适配器模式讲解
    • 2.1 核心类及类图
    • 2.2 基本代码
  • 3、利用适配器模式解决问题
  • 4、适配器模式的应用实例
  • 5、总结
    • 5.1 解决的问题
    • 5.2 使用场景
    • 5.3 优缺点

1、真实开发场景的问题引入

假设现系统有一个日志接口,但是其实现性能比较低下,开发者想换一个高性能的日志框架时,遇到了新的框架和原先的接口不兼容的问题,这个时候应该怎么办?如何让新的日志框架适配原先的日志接口。

其实在不考虑设计模式的情况下,也可以想到解决方式,那就是在原先的接口实现中,使用新框架的接口和方法实现原来的功能。

但是因为使用的是框架,所以修改之前的实现不是个好办法,比较麻烦,此时就可以考虑适配器模式。

2、适配器模式讲解

适配器模式就是在两个层不兼容是采取的方案,简单说就是再加一个层。

2.1 核心类及类图

在这里插入图片描述
对于图中的Client,原先使用的FormerImpl的实例,现在想使用Adaptee的对象,没法直接使用因为接口已经固定了,代码中也都使用的是FormerImpl,不可能再去修改代码,所以定义一个Adapter对象,作为一个中间层,向Client提供Adaptee的功能。

2.2 基本代码

  • Target.java
public interface LogFace {
    void logInfo(String info);
}
  • FormerImpl.java
public class FormerImpl implements LogFace{
    @Override
    public void logInfo(String info) {
        System.out.println(info);
    }
}
  • Adaptee.java
@Slf4j
public class Adaptee {
    public void logInfo(String info){
        log.info("高性能日志实现"+info);
    }
}
  • Adapter.java
public class Adapter implements LogFace{
    private Adaptee adaptee = new Adaptee();
    @Override
    public void logInfo(String info) {
        adaptee.logInfo(info);
    }
}

  • LogFactory.java:使用工厂方法获取日志门对象
public class LogFactory {
	//更换日志实现,只需要在此处返回new Adapter的对象返回即可
    private static LogFace logFace = new Adapter();
    public static LogFace getInstance(){
        return logFace;
    }
}
  • Client.java
public class Client {
    public static void main(String[] args) {
        LogFace logFace = LogFactory.getInstance();
        logFace.logInfo("打印日志");
    }
}

注意:在实例代码中添加一个工厂方法,用于创建日志门面接口(LogFace)的实现对象,与更换日志实现之前相比,客户端代码没有任何改变。

3、利用适配器模式解决问题

见示例代码。

4、适配器模式的应用实例

适配器模式一个最典型的应用就是在SpringMVC中,HandlerAdapter就是扮演的适配器的角色。
在这里插入图片描述
当收到客户端请求时,DispatcherServlet首先根据请求的URL等从处理器映射器(HandlerMapping)中找是否有对应的处理器,然后交给对应的HandlerAdapter去执行其中的处理请求的方法。其中:

  • Target:HandlerAdapter接口扮演的适配器模式中的Target的角色,所有的适配器必须实现这个接口中。
  • Adapter:HandlerAdapter具体的实现类就是该模式中的Adapter,真正执行对应类型请求的处理方法。
  • Adaptee:Adaptee是Controller,例如@Controller, @RestController标注的类
  • Client:客户端就是SpringMVC框架。当请求到达时,它根据控制器的类型使用适当的HandlerAdapter。然后,HandlerAdapter调用控制器的方法来处理请求并产生响应。

注意:
这里的模式使用思路和上面说的不太一样,这里的Adaptee有很多(Controller一般是有很多),所以更多是为了适配不同的Controller去进行统一的处理器方法执行,和JDBC接口一样的作用。

但是本质就是加一层,屏蔽差异。所以本身面向接口编程就有点适配器模式的味道在里面了。

5、总结

5.1 解决的问题

主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。

5.2 使用场景

  1. 系统需要使用现有的类,而此类的接口不符合系统的需要。
  2. 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口
  3. 通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)

5.3 优缺点

  • 优点:(1)可以让任何两个没有关联的类一起运行。 (2)提高了类的复用。 (3)增加了类的透明度。 (4)灵活性好。
  • 缺点 (1)过多地使用适配器,会让系统非常零乱,不易整体进行把握。例如看到的是这个类,但实际执行的是另一个类。(2)由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

参考:
[1] 一次性搞懂设计模式–适配器模式 - 掘金 (juejin.cn)

[2] 适配器模式 | 菜鸟教程 (runoob.com)

[3] 秒懂设计模式之适配器模式(Adapter Pattern) - 知乎 (zhihu.com)

[4] Spring中的设计模式之适配器模式 - 知乎 (zhihu.com)

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

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

相关文章

前端:运用html+css+js模仿百度热搜电影榜鼠标移入特效

前端:运用htmlcssjs模仿百度热搜电影榜鼠标移入特效 1. 实现原理2. 界面布局3. js实现对鼠标移入和移出的监听4. 参考代码如下: 1. 实现原理 百度热搜上电影榜鼠标移入特效如上图所示。个人觉得上述特效实现原理为使用相对定位、绝对定位实现的(鼠标移入和没有移入…

关于ETL的两种架构(ETL架构和ELT架构)

ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。ETL一词较常用在数据仓库,但其对象…

华为、阿里巴巴、字节跳动 100+ Python 面试问题总结(五)

系列文章目录 个人简介:机电专业在读研究生,CSDN内容合伙人,博主个人首页 Python面试专栏:《Python面试》此专栏面向准备面试的2024届毕业生。欢迎阅读,一起进步!🌟🌟🌟 …

第五课:Figma 玻璃拟态页设计

效果展示 通过背景模糊实现玻璃拟态效果 选择合适的背景,绘制形状,给形状添加 Effects,点击下方的下拉选择框,选择 background blur;添加后会发现,画面无任何改变,调整 Fill 后面的百分比&…

6.运算符

6.1赋值运算符 ➢已经学过的赋值运算符: ➢其他赋值运算符: 、-、*、/、% 6.2 一元运算符 众多的JavaScript的运算符可以根据所需表达式的个数, 分为一元运算符、二元运算符、三元运算符 ●二元运算符: 例:let num1020 ●一元运算符: 例…

windows系统修改mysql8配置文件,关闭ssl验证

如何寻找配置文件 我的电脑,右键,管理,服务 找到MySQL8 右键,属性 找到配置文件位置 通常情况下的默认路径是: C:\ProgramData\MySQL\MySQL Server 8.0\my.ini 如何关闭SSL验证 打开 my.ini 配置内容如下&#x…

ant design vue a-table表格中插入操作按钮(以switch开关 [a-switch]为例)

1.给columns添加列属性 columns() {sortedInfo sortedInfo || {};return [{title: "工程",dataIndex: "outputProject",width: 80},{title: "是否显示小数",dataIndex: "showDecimalsOrnot",width: 80,scopedSlots: { customRender:…

Idea中git push to origin/master was rejected错误解决方案

Idea中git push to origin/master was rejected错误解决方案 问题描述解决方法 问题描述 idea开发中,需要将项目发布到gitee上,在gitee上创建仓库后,通过idea中git推送项目代码提示: push to origin/master was rejected 解决方法 gitee创建仓库时创建了README.md文件,本地…

Vue中TodoList案例_静态

MyHeader.vue <template><div class"todo-header"><input type"text" placeholder"请输入你的任务名称&#xff0c;按回车键确认"></div> </template><script> export default {name: "MyHeader"…

Postman怎么做接口测试-以简单的登录接口为例

我们就以登录某测试系统为例子&#xff0c;实现在Postman上做接口测试 一、首先打开系统首页首页&#xff0c;做一个登录操作&#xff08;目的是获取接口url及参数&#xff09;&#xff1a;一般在公司做接口测试的时候页面还没有出来&#xff0c;我们需要根据接口文档进行接口…

Terraform学习日记-AWS-EC2

terraform install https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli 这里我们使用 aws-linux-2022 作为执行环境 # sudo yum install -y yum-utils# sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/…

【Flutter问题记录】Android Studio不显示(右上角main.dart左边)设备栏

记录一下今天遇到的情况&#xff1a; 用android studio打开项目&#xff0c;我检查了&#xff0c;已经配置了flutter sdk和android sdk&#xff0c;但是右上角main.dart左边的设备栏就是不显示。 解决方法&#xff1a; 恢复如初&#xff1a;

统一观测丨使用 Prometheus 监控 Cassandra 数据库最佳实践

作者&#xff1a;元格 本篇内容主要包括四部分&#xff1a;Cassandra 概览介绍、常见关键指标解读、常见告警规则解读、如何通过 Prometheus 建立相应监控体系。 Cassandra 简介 Cassandra 是什么&#xff1f; Apache Cassandra 是一个开源、分布式、去中心化、弹性可伸缩、…

Ubuntu录屏软件Kazam

1. 安装 1.1. 桌面右键“打开终端” 1.2. 安装kazam这款软件。 sudo apt-get install kazam 2. 使用 2.1. 安装后打开&#xff0c;我们看看这款软件界面还是很友好很简洁的。 2.2. 除了录像我们还可以截图&#xff0c;也可以选择全屏、窗口、区域的方式录制。 2.3. 如果要录…

构建自己的ChatGPT:从零开始构建个性化语言模型

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【Unity2D】设置一物体默认在其他物体之上不被遮挡

比如我想让机器人显示在箱子的前面。 点击箱子&#xff0c;将其层级设置在机器人的后面。 即修改箱子的Order in Layer 在机器人之后 物体默认的Order in Layer 都是0 &#xff0c;将箱子的Order in Layer修改为-1即可 这样将确保先绘制机器人&#xff0c;然后绘制箱子。这样…

【小黄碎碎念】如何解析和替换字符串中的 Markdown 文本?正则表达式与 flexmark-java 库

前言 本周&#xff0c;笔者将之前的基于 Servlet 的个人博客项目进行了迭代&#xff0c;基于 SpringBoot SpringMVC Mybatis Redis 进行实现。额外实现密码的明文加密处理&#xff08;加盐算法&#xff09;、修改随笔、随笔主页等功能&#xff0c;并将 session 存储到 Redis…

App测试中ios和Android的区别

1、Android长按home键呼出应用列表和切换应用&#xff0c;然后右滑则终止应用&#xff1b; 2、多分辨率测试&#xff0c;Android端20多种&#xff0c;ios较少&#xff1b; 3、手机操作系统&#xff0c;Android较多&#xff0c;ios较少且不能降级&#xff0c;只能单向升级&…

ffmpeg中filter_query_formats函数解析

ffmpeg中filter_query_formats主要起一个pix fmt引用指定的功能。 下下结论&#xff1a; 先看几个结构体定义&#xff1a; //删除了一些与本次分析不必要的成员 struct AVFilterLink {AVFilterContext *src; ///< source filterAVFilterPad *srcpad; ///<…

Feign远程调用如何携带form url

这是一个需要携带参数在form url上的请求&#xff0c;正常调用方式是这样的 响应&#xff1a; 在Feign中&#xff0c;应该怎么调用呢?? 定义OpenFeignClient接口 FeignClient(value "client-service", url "http://127.0.0.1/api") public interface…
最新文章