Java设计模式 —— 【结构型模式】适配器模式(类的适配器、对象适配器、接口适配器)详解

文章目录

  • 基本介绍
  • 一、类的适配器
  • 二、对象适配器
  • 三、接口适配器
  • 总结


基本介绍

生活中有很多例子:

  • 不同国家的插座接口不同,需要转换器;
  • 家用电源220V,手机只接受5V充电,需要转换器;
  • 读卡器,拓展坞。。。

在这里插入图片描述
定义:

​ 适配器模式的主要作用是将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

​ 适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

结构:

适配器模式(Adapter)包含以下主要角色:

  • 目标(Target)接口: 当前系统业务所期待的接口,它可以是抽象类或接口;
  • 适配者(Adaptee)类: 它是被访问和适配的现存组件库中的组件接口;
  • 适配器(Adapter)类: 它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

一、类的适配器

实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

【例】手机充电器

家用电源220V,手机只接受5V充电,要想给手机充电,我们得需要一个转换器。

在这里插入图片描述
家用电源【适配者类】:

public class Voltage220V {public Integer output22V() {return 220;}
}

目标接口:

//充电器接口
public interface IVoltage5V {Integer output5V();
}//给个实现类
public class Voltage5V implements IVoltage5V {@Overridepublic Integer output5V() {return 5;}
}

适配器类:

public class VoltageAdapter extends Voltage220V implements IVoltage5V {@Overridepublic Integer output5V() {return 5;}
}

手机类:

public class Phone {public void charging(IVoltage5V iVoltage5V) {if(iVoltage5V.output5V() == 5) {System.out.println("电压5V, 正在充电。。。");} else {System.out.println("只能使用5V电压充电。。。");}}
}

测试:

public class Client {public static void main(String[] args) {Phone phone = new Phone();System.out.println("===直接使用5V电源充电===");phone.charging(new Voltage5V());System.out.println("===使用类适配器充电===");phone.charging(new VoltageAdapter());}
}

在这里插入图片描述
小结:

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

二、对象适配器

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

使用对象适配器将上述案例做以修改后,UML类图为:

在这里插入图片描述
家用电源【适配者类】:

public class Voltage220V {public Integer output220V() {return 220;}
}

目标接口:

public interface IVoltage5V {Integer output5V();
}public class Voltage5V implements IVoltage5V {@Overridepublic Integer output5V() {return 5;}
}

适配器类:

public class VoltageAdapter implements IVoltage5V {private Voltage220V voltage220V;public VoltageAdapter(Voltage220V voltage220V) {this.voltage220V = voltage220V;}@Overridepublic Integer output5V() {//适配规则Integer v220 = voltage220V.output220V();return v220 / 44;}
}
public class Phone {public void charging(IVoltage5V iVoltage5V) {System.out.println("正在充电, 电压" + iVoltage5V.output5V() + "V");}
}

测试:

public class Demo2 {public static void main(String[] args) {Phone phone = new Phone();System.out.println("===直接使用5V电源充电===");phone.charging(new Voltage5V());System.out.println("===使用对象适配器充电===");phone.charging(new VoltageAdapter(new Voltage220V()));}
}

在这里插入图片描述

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

三、接口适配器

  1. 适配器又叫缺省适配器模式;
  2. 核心思路:当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求;
  3. 适用于一个接口不想使用其所有的方法的情况。
    在这里插入图片描述

总结

结构:

  • 类适配器:以类给到适配器,在 Adapter 里,就是将 src 当做类,继承;
  • 对象适配器:以对象给到适配器,在 Adapter 里,将 src 作为一个对象,持有;
  • 接口适配器:以接口给到适配器,在 Adapter 里,将 src 作为一个接口,实现。

优点:

  • 适配器模式最大的作用还是将原本不兼容的接口融合在一起工作;

  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构;

  • 增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用;

  • 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”;

  • 对象适配器避免了但继承的缺点,可以把多个不同的适配者适配到同一个目标。

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

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

相关文章

分页查询在数据库中的好处

分页查询在数据库中的好处主要体现在以下几个方面: 提高性能: 减少数据传输:分页查询只返回请求的页面数据,而不是整个数据集,这减少了网络传输的数据量,降低了网络延迟和带宽消耗。减少内存使用&#xff1…

启明智显ZX7981PC:5G时代的新选择,全屋网络无缝覆盖

在这个飞速发展的5G时代,每一个细微的科技进步都在推动着我们的生活向更加智能、便捷的方向发展。近日,启明智显再次引领科技潮流,正式发布其最新的5G CPE产品——ZX7981PC。作为继7981PG与7981PM之后的又一次迭代升级,ZX7981PC凭…

11篇--图像边缘检测

图像梯度 要学习图像边缘检测,要先了解图像梯度的概念,我们正是通过梯度值来区分边缘像素点的 处于边缘附近的像素点与周围像素点的差距很大(不然不会有边缘呈现),所以给边缘附近的的梯度之变化很快,通过…

6.2 MapReduce工作原理

MapReduce工作原理涉及将大数据集分割成小块并行处理。Map任务读取数据块并输出中间键值对,而Reduce任务则处理这些排序后的数据以生成最终结果。MapTask工作包括读取数据、应用Map函数、收集输出、内存溢出时写入磁盘以及可选的Combiner局部聚合。ReduceTask工作则…

[ Pytorch教程 ] 0、环境安装

好久前学下pytorch的使用,整理下发个系列出来 1、安装 conda 环境及 pytorch环境 把需要用的环境安装到位,python的虚拟环境以及pytorch环境 #安装 conda conda create -n pytorch python3.6#pytorch官网查找安装命令 https://pytorch.org/ conda inst…

OpenCV圆形标定板检测算法findGrid原理详解

class CirclesGridClusterFinder {CirclesGridClusterFinder(const CirclesGridClusterFinder&); public:CirclesGridClusterFinder(bool _isAsymmetricGrid){

解决docker环境下aspose-words转换word成pdf后乱码问题

描述 环境&#xff1a;docker 部署工具&#xff1a;Jenkins 需求&#xff1a;本地上传的word文档需要转换成pdf 问题&#xff1a;转换之后的pdf文档出现小框框&#xff08;乱码&#xff09; 转换成PDF的操作 pom&#xff1a; <dependency><groupId>org.apach…

ARM Cortex-A7 MPCore 架构

1、Cortex-A7 MPCore 简介 Cortex-A7 MPcore 处理器支持 1~4 核&#xff0c;通常是和 Cortex-A15 组成 big.LITTLE 架构的&#xff0c; Cortex-A15 作为大核负责高性能运算&#xff0c;比如玩游戏啥的&#xff0c; Cortex-A7 负责普通应用&#xff0c;因为 CortexA7 省电。 Co…

[echarts] vue-echarts vue3

vue3 npm i echarts vue-echartssrc/main.js import { createApp } from vue import { createPinia } from piniaimport App from ./App.vue import router from ./routerimport * as echarts from echarts const app createApp(App)// 全局挂载 echarts app.config.globalPr…

Guava 提供了 `List`、`Set` 和 `Map` 三个工具类

以下是使用Google Guava库中的工具方法来创建和操作List、Set、Map集合的一些示例&#xff1a; List相关操作 创建List 使用Lists.newArrayList()创建一个新的可变ArrayList实例。List<Integer> list Lists.newArrayList(1, 2, 3);// 创建不可修改的列表List<String…

天天 AI-241215:今日热点-OpenAI发布ChatGPT Projects,万能工具箱上线!

2AGI.NET | 探索 AI 无限潜力&#xff0c;2AGI 为您带来最前沿资讯。 2024年&#xff0c;人工智能&#xff08;AI&#xff09;领域的发展日新月异&#xff0c;不断刷新我们对技术边界的认知。从预训练模型的终结宣言到AI应用开发平台的受欢迎程度&#xff0c;再到AI在数据管理和…

CEF127 编译指南 MacOS 篇 - 安装 Git 和 Python(三)

1. 引言 在前面的文章中&#xff0c;我们已经完成了 Xcode 及基础开发工具的安装和配置。接下来&#xff0c;我们需要安装两个同样重要的工具&#xff1a;Git 和 Python。这两个工具在 CEF 的编译过程中扮演着关键角色。Git 负责管理和获取源代码&#xff0c;而 Python 则用于…

手机静态ip地址怎么获取?方法全解析‌

在数字化时代&#xff0c;智能手机已成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;手机都扮演着至关重要的角色。而在某些特定情境下&#xff0c;我们可能需要为手机设置一个静态IP地址。本文将详细介绍如何为手机获取静态IP地址。 一、通过手机设…

FlightAD 解读

一 文章相关信息 出处&#xff1a;ICPADS CCF C 会议&#xff08;代码未开源&#xff09;&#xff0c;COUTA 研究团队的另一研究 二 Methodology 1. 整体架构&#xff1a; 2. Multi-Scale Sampling&#xff08;多尺度&#xff09; 实际上&#xff0c;就是对每个单通道作 “多…

【考前预习】4.计算机网络—网络层

往期推荐 【考前预习】3.计算机网络—数据链路层-CSDN博客 【考前预习】2.计算机网络—物理层-CSDN博客 【考前预习】1.计算机网络概述-CSDN博客 目录 1.网络层概述 2.网络层提供的两种服务 3.分类编址的IPV4 4.无分类编址的IPV4—CIDR 5.IPV4地址应用规划 5.1使用定长子…

C# 结构体和类

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、类&#xff08;Class&#xff09;二、结构体&#xff08;Struct&#xff09;示例代码&#xff08;定义类和结构体&#xff09;类的继承代码示例&#xff08…

github配置pages并配置自定义域名

有cloudflare的话实现的效果更好&#xff0c;可以使用自己的域名&#xff0c;实现白嫖一个网站服务器 1、配置git&#xff08;可选步骤&#xff09; git init git config --global user.name "sijia" git config --global user.email "devopsgame.vip"g…

vue3 结合 echarts 为tooltip绑定点击事件实现树形结构下动态添加子节点的效果

先看效果 具体实现代码如下&#xff1a; <template> <div ref"ecs" id"ecs" style"width: 800px;height:800px; background-color:white;"></div> </template><script setup> import {onMounted, ref} from &quo…

【JavaWeb后端学习笔记】Redis常用命令以及Java客户端操作Redis

redis 1、redis安装与启动服务2、redis数据类型3、redis常用命令3.1 字符串String3.2 哈希Hash3.3 列表List3.4 集合Set&#xff08;无序&#xff09;3.5 有序集合zset3.6 通用命令 4、使用Java操作Redis4.1 环境准备4.2 Java操作字符串String4.3 Java操作哈希Hash4.4 Java操作…

js:我要在template中v-for循环遍历这个centrerTopdata,我希望自循环前面三个就可以了怎么写

问&#xff1a; 我按在要在template中v-for循环遍历这个centrerTopdata&#xff0c;我希望自循环前面三个就可以了怎么写&#xff1f; 回答&#xff1a; 问&#xff1a; <div v-for"(item, index) in centrerTopdata.slice(0, 3)" :key"index"> d…