设计模式篇(Java):适配器模式

news2024/11/13 15:56:24

设计模式篇(Java):建造者模式

八、适配器模式

8.1 适配器模式基本介绍

生活中的适配器例子

  • 比如生活中的插座,在不同国家插座有着不同的规格,如果我们从一个国家去另外一个国家需要使用插座时就需要一个中间转换器把两种不同规则的插座适配一下。
  • 生活中电脑充电器,手机充电器,手机电脑可能支持20v充电,但是生活用电时220v,所以产家加载充电器上做了适配器,把插座过来的220v适配成手机能适应的20v

基本介绍

  • 适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)。
  • 适配器模式属于结构型模式。
  • 主要分为三类:类适配器模式、对象适配器模式、接口适配器模式

工作原理

  • 适配器模式:将一个类的接口转换成另一种接口。让原本接口不兼容的类可以兼容。
  • 从用户的角度看不到被适配者,是解耦的。
  • 用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法。
  • 用户收到反馈结果,感觉只是和目标接口交互。用户感受不到适配的过程。

8.2 类适配器模式

生活示例:充电器。充电器本身相当于Adapter,220V交流电相当于src(即被适配者),我们的目dst(即目标)是20V直流电。

在这里插入图片描述

代码示例

被适配的类(220V)

/**
 * @author cVzhanshi
 * @create 2023-06-25 16:33
 */

@Slf4j
public class Voltage220V {
    public int output220V() {
        int src = 220;
        log.info("电压 = {}V", src);
        return src;
    }
}

适配接口

/**
 * @author cVzhanshi
 * @create 2023-06-25 16:35
 */
public interface IVoltage5V {
    int output5V();
}

适配类

/**
 * @author cVzhanshi
 * @create 2023-06-25 16:36
 */
public class VoltageAdapter extends Voltage220V implements IVoltage5V{
    @Override
    public int output5V() {
        // 获得220v电压
        int src = output220V();
        // 转化成手机能用的5v
        int dst = src / 44;
        return dst;
    }
}

手机类以及客户端

/**
 * @author cVzhanshi
 * @create 2023-06-25 16:38
 */
@Slf4j
public class Phone {
    // 充电
    public void init (IVoltage5V iVoltage5V) {
        if (iVoltage5V.output5V() == 5) {
            log.info("电压为5v,可以充电");
        } else {
            log.info("电压大于5v,不能充电");
        }
    }
}

/**
 * @author cVzhanshi
 * @create 2023-06-25 16:40
 */
public class Client {
    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.init(new VoltageAdapter());
    }
}

这样就是通过适配器解决了电压不适配的问题

类适配器模式注意事项和细节

  • Java是单继承机制,所以类适配器需要继承被适配类这一点算是一个缺点,因为这要求dst必须是接口,有一定局限性。
  • src类的方法在Adapter中都会暴露出来,也增加了使用的成本。
  • 由于其继承了src类,所以它可以根据需求重写src类的方法,使得Adapter的灵活性增强了。

8.3 对象适配器模式

  • 与类适配器唯一不同的是,对象适配器模式是持有src类,而不是继承src类。
  • 使用了关联或者聚合的关系代替了继承

那么类图就变成了

在这里插入图片描述

代码主要是适配器代码的区别:

适配器

/**
 * @author cVzhanshi
 * @create 2023-06-25 16:36
 */
public class VoltageAdapter extends Voltage220V implements IVoltage5V{
	private Voltage220V voltage220V;
	
	public VoltageAdapter (Voltage220V voltage220V) {
		this.voltage220V = voltage220V;
	}
	
    @Override
    public int output5V() {
        // 获得220v电压
        int src = voltage220V.output220V();
        // 转化成手机能用的5v
        int dst = src / 44;
        return dst;
    }
}

对象适配器的注意事项和细节

  • 组合代替了继承,解决了类适配器需要继承src的局限性,也不需要要求dst必须是接口。

  • 使用成本低,更灵活。

8.4 接口适配器模式

  • 接口适配器模式也可以称为缺省适配器模式
  • 核心思路:当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法), 那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求
  • 适用于一个接口不想使用其所有的方法的情况。

代码演示

接口

public interface IVoltage {
    void output5V();
    
    void output10V();
    
    void output15V();
    
    void output20V();
}

适配器

/**
 * @author cVzhanshi
 * @create 2023-06-25 17:08
 */
public abstract class Adapter implements IVoltage{
    @Override
    public void output5V() {
        
    }

    @Override
    public void output10V() {

    }

    @Override
    public void output15V() {

    }

    @Override
    public void output20V() {

    }
}

然后使用者再根据需求重写某些方法就可以

8.5 适配器模式在SpringMVC中的运用

在DispatcherServlet类中

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
   // ...

    ModelAndView mv = null;
    Exception dispatchException = null;


    processedRequest = checkMultipart(request);
    multipartRequestParsed = (processedRequest != request);

    // Determine handler for the current request.
    // 确定当前请求的处理程序,根据request来获取Handler
    mappedHandler = getHandler(processedRequest);
    if (mappedHandler == null) {
        noHandlerFound(processedRequest, response);
        return;
    }

    // Determine handler adapter for the current request.
    // 确定当前请求的处理程序适配器 根据handler来获取适配器
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

   // ...

    // Actually invoke the handler.
    // 实际上调用处理程序
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());


   // ...

    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);


}

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

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

相关文章

【数据结构导论】第 3 章:栈、队列和数组

目录 一、栈 (1)栈的基本概念 ① 定义 ② 示意图 ③ 栈的特点 ④ 栈的基本运算 (2)栈的顺序实现 ① 顺序栈及常用名词 ② 顺序栈的类型定义 ③ 顺序栈的基本运算 Ⅰ. 初始化 Ⅱ. 判栈空 Ⅲ. 进栈 Ⅳ. 出栈 Ⅴ. …

【JavaSE】程序逻辑控制

目录 【1】概念 【2】顺序结构 【3】分支结构 【3.1】if 语句 【3.2】switch 语句 【4】循环结构 【4.1】while 循环 【4.2】for 循环 【4.3】do while 循环 【4.4】break 关键字 【4.5】continue 关键字 【5】输入输出 【5.1】输出到控制台 【5.2】从键盘输入 …

第38节:cesium 风场效果(含源码+视频)

结果示例: 完整源码: <template><div class="viewer"><vc-viewer @ready="ready" :logo="false"><!

抖音seo矩阵系统源码开发部署|抖音小程序接入(一)

一、 开发部署步骤&#xff1a; &#xff08;1&#xff09;申请开放平台服务商 &#xff08;2&#xff09;申请开放平台网站应用 &#xff08;3&#xff09;申请开放平台应用权限 &#xff08;4&#xff09;提交各个API接口申请文档 &#xff08;5&#xff09;审核通过技…

JVM实战-2023线上项目突发OOM以及快速定位解决全过程

现象描述&#xff1a; 用户在进行报表下载过程中&#xff0c;每隔几天系统就会报错500&#xff0c;导致无法进行报表下载。 原因分析: 通过查看系统log日志以及gc日志&#xff0c;发现是因为下载报表过程中JVM频繁进行Full GC&#xff0c;而且老年代的堆内存不断增加且无法回…

chatgpt赋能python:Python彻底删除指南:为什么需要彻底删除Python?

Python彻底删除指南&#xff1a;为什么需要彻底删除Python&#xff1f; Python是一种高级编程语言&#xff0c;它广泛用于各种应用程序的开发。但是&#xff0c;对于某些开发者来说&#xff0c;可能需要从他们的计算机中彻底删除Python。这可能是因为他们需要将Python版本更新…

Linux--打印内容或者插入内容:echo

语法&#xff1a; echo 内容 作用&#xff1a;打印内容到显示器echo 内容 > 不存在的文件 作用&#xff1a;文件创建&#xff0c;并将内容插入新创建的文件中echo 内容 > 存在的文件 作用&#xff1a;覆盖文件原有的内容 echo 内容 >> 存在的文件 作用&#xff1a…

Redis的持久化机制(2)

AOF 以独立日志的方式记录每次写命令&#xff08;读操作不记录&#xff09;&#xff0c;重启时再重新执行AOF文件中的命令来恢复数据。AOF会先把命令追加在AOF缓冲区&#xff0c;然后根据对应策略写入硬盘&#xff08;appendfsync&#xff09;&#xff0c;它只许追加文件但不可…

【vue:淘宝rem自适应 】

vue:淘宝rem自适应 1.安装lib-flexible&#xff1a;cnpm install lib-flexible --save 2.在main.js中引入&#xff1a;import lib-flexible/flexible.js’ 3.配置flexible找到vue-cli路径node_modules/lib-flexible/flexible.js&#xff0c;然后修改rem换算单位 4.配置px to re…

ThreadLocal-线程安全利器

原文链接&#xff1a;https://www.jylt.cc/#/detail?activityIndex2&id9df3fd62d6ee13ff555c30157798b092 ThreadLocal是什么 ThreadLocal用来提供线程内部的局部变量&#xff0c;是各个线程独有的&#xff0c;该变量无法被其他线程访问。主要有以下作用&#xff1a; 解…

pyqt5实现线程与弹窗功能

pyqt5实现线程与弹窗功能 效果图&#xff1a; 示例下载 点我下载 https://download.csdn.net/download/lm_is_dc/87982279 简介 Pyqt5线程使用 QThread, pyqtSignal, QMutex, QWaitCondition来实现&#xff0c;涉及到线程&#xff0c;锁&#xff0c;信号量&#xff0c;线程…

深入理解计算机系统(2)_计算机基本组成

深入理解计算机系统系列文章目录 第一章 计算机的基本组成 1. 内容概述 2. 计算机基本组成 第二章 计算机的指令和运算 第三章 处理器设计 第四章 存储器和IO系统 文章目录 深入理解计算机系统系列文章目录前言参考资料一、组成架构&#xff08;冯/图&#xff09;1. 组成架构2…

42. 接雨水

题目链接&#xff1a;力扣 解题思路&#xff1a;从左往右按列进行计算&#xff0c;依次计算每一列能够接到的雨水数量。对于当前列能够接到的雨水数量是由左右两边最高的两根柱子决定的&#xff0c;类似于木桶定律&#xff08;一只水桶能装多少水取决于它最短的那块木板&#x…

AI实践-定制你的专属简历-软件测试

简历对于找到一份理想的工作至关重要。但是&#xff0c;准备简历这一过程却让人感到头疼和繁琐&#xff0c;而且如何突出自己的优势&#xff0c;也是许多求职者遇到困惑。 chatgpt不会受到情感和个人喜好的影响&#xff0c;能够通过算法和数据分析为您编写最合适的简历。并且可…

目标检测算法-YOLOV5解析(附论文与源码)

目标检测算法-YOLOV5解析&#xff08;附论文与源码&#xff09;

数据结构 | 顺序二叉树

一、数据结构定义 1、顺序二叉树 /* 顺序二叉树 */ typedef char TreeType; typedef struct seqTree{int MAXNUM; // 最大元素个数int curNum; // 元素的个数TreeType nodelist[]; // 顺序二叉树节点存储 } *SeqTree; 本次代码中二叉树的结构如下图&#xff0c;用层次序列可…

【Python】字典

文章目录 一. 字典的创建二. 字典的操作1. 查找 key2. 新增键值对3. 删除键值对4. 遍历字典4.1 使用 for 循环遍历字典4.2 通过方法遍历字典keys() 获取到字典中所有 keyvalues() 获取到字典中的所以 valueitems 获取到字典中的所有键值对 三. 理解字典操作的效率 一. 字典的创…

Linux--打印文件内容:cat

cat是cater的简写 语法&#xff1a; cat [选项] [文件] 常用选项&#xff1a; -b 对非空输出行编号 -n 对输出的所有行编号 -s 不输出多行空行 示例&#xff1a; ①打印文件hello.c的内容 ②带行号打印文件hello.c的内容 ③输入什么&#xff0c;打印什么 ④输入重定向&…

讲座笔记:如何撰写高质量科技论文

1 论文总体思路 2 摘要 3 Intro 常见Introduction逻辑&#xff1a; 说明问题是什么&#xff1b;简单罗列前人工作&#xff1b;描述我们的工作。 说明问题是什么&#xff1b;目前最好的工作面临什么挑战&#xff1b;我们的方法能缓解上述挑战 3.1 段落写法 首先列出几句话 …

【 Linux】文件删除原理

文章目录 Linux文件删除原理文件的索引节点和链接文件删除的过程文件删除后是否能恢复 Linux文件删除原理 Linux是一个强大的操作系统&#xff0c;它提供了许多命令和工具来管理文件和目录。其中&#xff0c;最常用的命令之一就是rm&#xff0c;它可以用来删除不需要的文件或目…