Java设计模式-适配器模式Adapter

news2024/11/28 16:34:50

在这里插入图片描述

介绍

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

工作原理

  1. 适配器模式:将一个类的接口转换成另一种接口.让原本接口不兼容的类可以兼容
  2. 从用户的角度看不到被适配者,是解耦的
  3. 用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法
  4. 用户收到反馈结果,感觉只是和目标接口交互,如图:
    在这里插入图片描述

类适配器

介绍

Adapter 类,通过继承 src 类,实现 dst 类接口,完成 src->dst 的适配。

案例

  1. 应用实例说明以生活中充电器的例子来讲解适配器,充电器本身相当于 Adapter,220V 交流电相当于 src (即被适配者),我们的目 dst(即 目标)是 5V 直流电
  2. 思路分析(类图):
    在这里插入图片描述
  • 代码实现:
public interface IVoltage5V {
  public int output5V();
}

//被适配的类
public class Voltage220V {
//输出 220V 的电压
	public int output220V() {
		int src = 220;
		System.out.println("电压=" + src + "伏");
		return src;
	}
}

public class VoltageAdapter extends Voltage220V implements IVoltage5V {
	@Override
	public int output5V() {
        //获取到 220V 电压
		int srcV = output220V();
		int dstV = srcV / 44; // 转成 5v
		return dstV;
	}
}
public class Phone {
	// 充电
	public void charging(IVoltage5V iVoltage5V) {
		if (iVoltage5V.output5V() == 5) {
			System.out.println("电压为 5V, 可以充电~~");
		} else if (iVoltage5V.output5V() > 5) {
			System.out.println("电压大于 5V, 不能充电~~");
		}
	}
}
public class Client {
	public static void main(String[] args) {
		System.out.println(" === 类适配器模式 ====");
		Phone phone = new Phone();
		phone.charging(new VoltageAdapter());
	}
}

注意事项

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

对象适配器模式

介绍

  1. 基本思路和类的适配器模式相同,只是将 Adapter 类作修改,不是继承 src 类,而是持有 src 类的实例,以解决
    兼容性的问题。 即:持有 src 类,实现 dst 类接口,完成 src->dst 的适配
  1. 根据“合成复用原则”,在系统中尽量使用关联关系(聚合)来替代继承关系。
  2. 对象适配器模式是适配器模式常用的一种

案例

  1. 以生活中充电器的例子来讲解适配器,充电器本身相当于 Adapter,220V 交流电相当于 src (即被适配者),我们的目 dst(即目标)是 5V 直流电,使用对象适配器模式完成。
  1. 思路分析(类图):只需修改适配器即可, 如下:
    在这里插入图片描述
  • 代码实现
//适配接口
public interface IVoltage5V {
  public int output5V();
}

//被适配的类
public class Voltage220V {
//输出 220V 的电压,不变
	public int output220V() {
		int src = 220;
		System.out.println("电压=" + src + "伏");
		return src;
	}
}

public class Phone {
    //充电
	public void charging(IVoltage5V iVoltage5V) {
		if (iVoltage5V.output5V() == 5) {
			System.out.println("电压为 5V, 可以充电~~");
		} else if (iVoltage5V.output5V() > 5) {
			System.out.println("电压大于 5V, 不能充电~~");
		}
	}

}
//适配器类
public class VoltageAdapter implements IVoltage5V {
	private Voltage220V voltage220V; // 关联关系-聚合
    //通过构造器,传入一个 Voltage220V 实例
	public VoltageAdapter(Voltage220V voltage220v) {
		this.voltage220V = voltage220v;
	}

	@Override
	public int output5V() {
		int dst = 0;
		if (null != voltage220V) {
			int src = voltage220V.output220V();// 获取 220V 电压
			System.out.println("使用对象适配器,进行适配~~");
			dst = src / 44;
			System.out.println("适配完成,输出的电压为=" + dst);
		}
		return dst;
	}
}
public class Client {
	public static void main(String[] args) {
		System.out.println(" === 对象适配器模式 ====");
		Phone phone = new Phone();
		phone.charging(new VoltageAdapter(new Voltage220V()));
	}
}

注意事项

  1. 对象适配器和类适配器其实算是同一种思想,只不过实现方式不同。根据合成复用原则,使用组合替代继承, 所以它解决了类适配器必须继承 src 的局限性问题,也不再要求 dst必须是接口。
  2. 使用成本更低,更灵活。

接口适配器模式

介绍

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

案例

  1. Android 中的属性动画 ValueAnimator 类可以通过addListener(AnimatorListener listener)方法添加监听器, 那么
    常规写法如右:

  2. 有时候我们不想实现 Animator.AnimatorListener 接口的全部方法,我们只想监听 onAnimationStart,我们会如下写
    在这里插入图片描述

  3. AnimatorListenerAdapter 类,就是一个接口适配器,代码如右图:它空实现了Animator.AnimatorListener 类(src)的所有方法.

  4. AnimatorListener 是一个接口
    在这里插入图片描述

  5. 程序里的匿名内部类就是 Listener 具体实现类
    在这里插入图片描述

注意事项

HandlerAdapter源码剖析

  1. SpringMvc 中的 HandlerAdapter, 就使用了适配器模式
  2. SpringMVC 处理请求的流程回顾
  3. 使用 HandlerAdapter 的原因分析:
    可以看到处理器的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用 Controller 方法,需要调用的时候就得不断是使用 if else 来进行判断是哪一种子类然后执行。那么如果后面要扩展 Controller,就得修改原来的代码,这样违背了 OCP 原则。
  4. 代码分析+Debug 源码
    在这里插入图片描述
    在这里插入图片描述

注意事项

  1. 三种命名方式,是根据 src 是以怎样的形式给到 Adapter(在 Adapter 里的形式)来命名的。
  2. 类适配器:以类给到,在 Adapter 里,就是将 src 当做类,继承
    对象适配器:以对象给到,在 Adapter 里,将 src 作为一个对象,持有
    接口适配器:以接口给到,在 Adapter 里,将 src 作为一个接口,实现
  3. Adapter 模式最大的作用还是将原本不兼容的接口融合在一起工作。
  4. 实际开发中,实现起来不拘泥于我们讲解的三种经典形式

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

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

相关文章

树莓派自带的python3.9->python3.7

卸载python3.9:sudo apt-get remove python3卸载之后一些包可以使用sudo apt autoremove这个命令删除卸载成功如果出现问题后续再来更新(出现问题后后续安装python也会失败)(先不要安装先看)安装python3.7:…

C语言第30课笔记

1.strerror(errno要包含头文件errno.h) 2.perror头文件为stdio.h 3.一些字符函数 4.字母大小写转换函数 5.memmove理论上是memcpy的升级版(可以自己拷贝自己)。 6.匿名结构体类型在类型创建好了之后直接创建变量,只能用一次。两个完全相同的匿名结构体类型&#xf…

【八】Netty HTTP协议--文件服务系统开发

Netty HTTP协议--文件服务系统开发介绍HTTP-文件系统场景描述流程图代码展示netty依赖服务端启动类 HttpFileServer服务端业务逻辑处理类 HttpFileServerHandler结果展示错误路径文件夹路径文件路径遗留bugbug版本总结介绍 由于Netty天生是异步事件驱动的架构,因此…

java EE初阶 — Synchronized 的原理

文章目录1. Synchronized 的优化操作1.1 偏向锁1.2 轻量级锁(自旋锁)1.3 重量级锁2. 其他的优化操作2.1 锁消除2.2 锁粗化3. 相关面试题1. Synchronized 的优化操作 两个线程针对同一个对象加锁,就会产生阻塞等待。 Synchronized 内部其实还有…

ubuntu docker elasticsearch kibana安装部署

ubuntu docker elasticsearch 安装部署 所有操作尽量在root下操作. 安装docker 1. 由于是基于宝塔面板安装的所以简答的点击操作即可完成安装. 我这里已经是正常的安装好了. 2.dcoker 镜像加速 https://cr.console.aliyun.com/cn-hangzhou/instances访问这个网址进去进行了…

快速上手Golang

自动推导赋值:自动推导赋值Go中 不同的数据类型不能进行计算对于浮点型默认都是float64 精确到小数点后15位单引号的 为字节类型 一位0~255的字符转换双引号的 为字符串类型多重赋值多重赋值a,b:1,2格式输出格式输出printf“%3d”三位整数,不满足三位时头部补空格“…

录制课程用什么软件好?3款超好用的课程视频录课软件

在互联网技术的飞速发展下,在线教学已经成为一种新型的教学形式,与传统的教学方法相比,在线教学具有低成本、突破地域、时间灵活、形式多样的教学方式。那录制课程用什么软件好?今天小编就跟大家分享3款超好用的课程视频录课&…

认真研究MySQL的主从复制(一)

【1】主从复制概述 ① 如何提升数据库并发能力 在实际工作中,我们常常将Redis作为缓存与MySQL配合使用,当有请求的时候,首先会从缓存中进行查找。如果存在就直接取出,如果不存在再访问数据库。这样就提升了读取的效率&#xff0…

中国数据库的诸神之战

作者 | 唐小引出品 | 《新程序员》编辑部“现在的数据库产品实在是太多了!”前几天,我和深耕数据库/大数据近 30 年的卢东明老师相聊时,他发出了这样的感慨。将包括 DB-Engines Ranking 以及国内数据库排行等在内的数据库产品列表进行汇总&am…

快速入门Freemarker模块引擎技术

1、 freemarker 介绍 ​ FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库&am…

采场的车辆管理及卸料点计数管理有哪些难题需要解决

近期,安环部检查采矿区域工程车辆驾驶人员情况时,发现有部分驾驶员及工作人员存在违规顶替情况,有非注册备案人员驾驶矿用工程车辆违规作业。为了进行统一有效的人员车辆管理,同时能监督安全员定期对采矿作业区进行安全巡查&#…

Camtasia Studio2023喀秋莎新增功能及电脑配置要求介绍

Camtasia Studio2023具有强大的视频播放和视频编辑功能,录制屏幕后,根据时间轴对视频剪辑进行各种标记、媒体库、画中画、画中画、画外音当然,也可以导入现有视频并对其进行编辑操作。编辑完成后,可以将录制的视频输出为最终的视频…

光伏废水深度除氟装置,用于高盐废水除氟的工艺

光伏行业废水根据生产产品可细分为单品硅生产线排水、多品硅生产线排水。其生产工序中有污水排放的工段主要是:制绒和清洗工段。废水中的主要污染物为由异丙醇引起的高浓度COD、氟离子及酸碱污染,其中以含异丙醇的废水一直是水处理中的难题。如果不对废水…

【自学Python】Python input()函数

Python input()函数 Python input()函数教程 在 Python 中,input() 函数用于获取用于的输入,并给出提示。input() 函数,总是返回 string 类型,因此,我们可以使用 input() 函数,获取用户输入的任何数据类型…

【C进阶】第十五篇——内存函数

memcpy - 内存拷贝1 函数介绍 模拟实现 memmove - 内存拷贝2 函数介绍 模拟实现 memcmp - 内存比较 memset - 内存设置 memcpy - 内存拷贝1 函数介绍 void *memcpy( void *dest, const void *src, size_t count );memcpy函数是一个用于拷贝两个不相关的内存块的函数。…

4-2文件管理-文件系统实现

文章目录一.文件系统层次结构二.文件系统的全局结构三.虚拟文件系统与文件系统挂载(安装)(一)虚拟文件系统(二)文件系统挂载(安装)一.文件系统层次结构 (1)用…

密码学_MD5算法

MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。 MD5算法具有以下特点&#xff1a…

php宝塔搭建部署实战易优cms皮具皮包手袋定制网站源码

大家好啊,我是测评君,欢迎来到web测评。 本期给大家带来一套php开发的易优cms皮具皮包手袋定制网站源码,感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&a…

Java 日常开发记录

手动分页 非mybatis 自动分页 service 层 Overridepublic PageInfo<CfLogVo> cfLogList(CfLogQuery cfLogQuery) {if (StrUtil.isNotBlank(cfLogQuery.getRequest()) && cfLogQuery.getRequest().length() >100){throw new ServiceException("请求报文…

Flutter | 使用 typedef 让回调更优雅

今天来谈谈 Flutter 的 typedef。 一. 熟悉的 VoidCallback 之前看 setState 源码的时候&#xff0c;发现它的参数是 VoidCallback&#xff1a; void setState(VoidCallback fn) {}VoidCallback 其实是一个自定义类型的无参数无返回值的匿名函数&#xff1a; /// Signature…