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

news2024/11/26 13:45:23

适配器的单词是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.coloradmin.cn/o/780589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2021年全国大学生电子设计竞赛H题——用电器分析识别装置

用电器分析识别装置 一、题目要求二、系统方案三、硬件设计3.1、ATT7022电参数采集模块 一、题目要求 任务 设计并制作一个根据电源线电流的电参量信息分析在用电器类别的装置。该装置具有学习和分析识别两种工作模式。在学习模式下,测试并存储用于识别各单件电器的…

百亿规模京东实时浏览记录系统的设计与实现 | 京东云技术团队

1. 系统介绍 浏览记录系统主要用来记录京东用户的实时浏览记录,并提供实时查询浏览数据的功能。在线用户访问一次商品详情页,浏览记录系统就会记录用户的一条浏览数据,并针对该浏览数据进行商品维度去重等一系列处理并存储。然后用户可以通过…

mybatis事物是如何和spring事物整合的

目录 1、mybatis事物管理器 2、SpringManagedTransactionFactory如何处理事物 3、spring事物如何设置connection连接到threadLocal 1、mybatis事物管理器 mybatis事物抽象接口类:Transaction。该接口定义了事物基本方法和获取数据库连接方法 该类有三个实现类Jd…

【本地开发快速添加localstoreage和cookie】

在本地开发时,通常会需要线上开发或测试环境的缓存,然而,如果缓存过多时,一个一个的复制key,value太过麻烦,于是本文介绍了一种快速设置缓存的方法。 cookie 需要用到插件,使用JSON格式导出&am…

PPT逻辑设计与完美呈现

PPT逻辑设计与完美呈现 https://haoxinyunxueyuan.zhixueyun.com/#/study/course/detail/detailInfoCD00——朱宁川 logo设计神器: https://www.zitijia.com/logodiy/index 一 PPT设计 第一章、PPT的灵魂设计-5W PPT灵魂设计(5W) 以终为始,从目标出发 why 目…

136. 只出现一次的数字

题目 题解一&#xff1a;采用map集合 class Solution {public static int singleNumber(int[] nums) {Map map new HashMap<Integer,Integer>();for (int i 0; i < nums.length; i) {//判断key是否重复&#xff0c;重复直接删掉重复的keyif (map.containsKey(nums[i…

JavaWeb 速通Servlet(请求转发和请求重定向)

目录 一、HttpServletRequest 1.简介 : 2.常用方法 : 1 getRequestURI() : 2 getRequestURL() : 3 getRemoteHost() : 4 getHeader(String header) : 5 getParameter(name) : 6 getParameterValues(name) : 7 getMethod() : 8 setAttribute(key, value) : 9 getAttrib…

面试之JVM的储存空间

Java8之后&#xff0c;取消了整个永久代区域&#xff0c;取而代之的是元空间。运行时常量池和静态常量池存放在元空间中&#xff0c;而字符串常量池依然存放在堆中。&#xff08;&#xff09; JVM允许时数据区 程序计数器的特点以及作用 &#xff1f; 1、程序计数器 是一块较…

protobuf学习

protobuf的安装 Windos版安装 下载地址&#xff1a;https://github.com/protocolbuffers/protobuf/releases 选择合适的版本下载 将下载的压缩包解压&#xff0c;把解压后文件的bin目录的路径配置到系统环境比变量Path中 在cmd 中执行 protoc --version 成功就说明安装成功了l…

Vue.js基础简答题

系列文章目录 后续补充 文章目录 系列文章目录前言一、库与框架的区别是什么&#xff1f;二、Vue.js 的核心特性有哪些&#xff1f;三、什么是数据驱动视图&#xff1f;四、MVVM 模型各部分含义是什么&#xff0c;在 Vue.js 中分别对应哪些功能&#xff1f;五、el 选项的作用是…

一)Stable Diffusion使用教程:安装

目前AI绘画最火的当属Midjorney和Stable Diffusion&#xff0c;但是由于Midjourney没有开源&#xff0c;因此我们主要分享下Stable Diffusion&#xff0c;后面有望补上Midjourney教程。 本节主要讲解Stable Diffusion&#xff08;以下简述SD&#xff09;的下载和安装。 1&…

uniapp查看ios打包后的Info.plist文件

最近在用 uni 开发 ios 的时候给项目添加了自定义的 Info.plist 文件&#xff0c;但是打包后发现并没有生效&#xff0c;才有了查看打包后的 Info.plist 文件想法。 HBuilderX3.6.5起&#xff0c;支持直接在应用项目中配置 iOS 平台的 Info.plist 和 资源文件&#xff08;Bundl…

pytest中生成allure报告时,测试报告中统计的用例数不正确

【问题描述】&#xff1a;pytest中生成allure报告时&#xff0c;测试报告中统计的用例数不正确&#xff0c;用例数总是比实际用例数多 【问题定位】&#xff1a;因为生成index.html的allure报告&#xff0c;是根据临时的json文件生成的。每次运行时&#xff0c;没有删除旧的js…

Grafana图形web监控的安装与配置

目录 一、安装并配置 二、Web访问 三、Grafana启用zabbix插件 四、Grafana添加zabbix数据源 五、创建仪表盘 创建监控项完成保存仪表盘 六、查看创建的仪表盘 七、在现有的dashboard&#xff08;仪表盘&#xff09;中添加图形 八、查看最终dashborad&#xff08;仪表盘&#x…

react 实现小球加入购物车动画

代码 import React, { useRef } from react;const ProductLayout () > {const box useRef(null);const createBall (left, top) > {const ball document.createElement(div);ball.style.position absolute;ball.style.left left - 10 px;ball.style.top top - 1…

三维点云中的坐标变换(只讲关键部分)

一、坐标旋转 坐标旋转包含绕x、y、z轴旋转&#xff0c;在右手坐标系中&#xff0c;x-翻滚(roll)&#xff0c;y-俯仰(pitch)&#xff0c;z-航向(yaw)。如果想详细了解&#xff0c;可以网络搜索 在PCL中&#xff0c;从baseLink到map的转换关系为:先绕x轴旋转,在绕y轴旋转,最后绕…

linux:secureCRT通过pem证书远程访问服务器

参考&#xff1a; secureCRT通过pem证书远程访问服务器_Fengshana的博客-CSDN博客 总结&#xff1a; 配置公钥即可

hdu7298 Coin(网络流+按时间拆点)

题目 t(t<10)组样例&#xff0c;每次给n(n<3e3)个人&#xff0c; 第i个人&#xff0c;在任意时刻&#xff0c;都最多只能有ai(1<ai<3e3)个硬币 其中k(k<n)个是小F的朋友&#xff0c;依次用点号的形式给出 初始时&#xff0c;每个人都有一个硬币&#xff0c;…

<j-editable-table 新增行 按钮去掉方法

新增行 按钮去掉方法 修改的内容 要去掉组件中的新增行添加按钮&#xff0c;你可以将:actionButton"true"的值改为:actionButton“false”&#xff0c;即将true改为false&#xff0c; 去掉前的 <j-editable-tableref"editableMeTable":loading"m…

react中使用echarts

下载插件 npm install echarts npm install echarts-for-react 引入模块 import ReactEcharts from "echarts-for-react" import echarts from "echarts"; import React from react; import ReactEcharts from echarts-for-react const Tiao () >…