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,一经查实,立即删除!

相关文章

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

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

11篇--图像边缘检测

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

6.2 MapReduce工作原理

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

ARM Cortex-A7 MPCore 架构

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

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

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

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

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

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

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

FlightAD 解读

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

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

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

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

有cloudflare的话实现的效果更好,可以使用自己的域名,实现白嫖一个网站服务器 1、配置git(可选步骤) 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…

前端成长之路:CSS(1)

在前端三件套中&#xff0c;CSS的主要是用于美化网页、进行页面布局的。 HTML的局限性 HTML是一个非常单纯的语言&#xff0c;它只关心内容的语义&#xff1a; 比如看见h1标签&#xff0c;就表明这是一个大标题、看见p标签&#xff0c;就表明这是一个段落、看见img标签&#…

微服务SpringCloud链路追踪之Micrometer+Zipkin

视频教程&#xff1a; https://www.bilibili.com/video/BV12LBFYjEvR 效果演示 当我们发送一个请求给 Gateway 的时候&#xff0c;由 Micrometer trace 进行链路追踪和数据收集&#xff0c;由 Zipkin 进行数据展示。可以清楚的看到微服务的调用过程&#xff0c;以及每个微服务…

0001.基于springmvc简易酒店管理系统后台

一.系统架构 springmvcjsplayuimysql 二.功能特性 简单易学习&#xff0c;虽然版本比较老但是部署方便&#xff0c;tomcat环境即可启用&#xff1b;代码简洁&#xff0c;前后端代码提供可统一学习&#xff1b;祝愿您能成尽快为一位合格的程序员&#xff0c;愿世界没有BUG; …

Elasticsearch Kibana (windows版本) 安装和启动

目录 1.安装 2.启动 elasticsearch 3.启动 kibana 1.安装 elasticsearch下载&#xff0c;官网链接&#xff1a; Download Elasticsearch | Elastichttps://www.elastic.co/downloads/elasticsearch kibana下载&#xff0c;官网链接&#xff1a; Download Kibana Free | G…

回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 CNN-BiGRU,即卷积神经网络(CNN)与双…

在C#中编程绘制和移动线段

这个示例允许用户绘制和移动线段。它允许您根据鼠标下方的内容执行三种不同的操作。 当鼠标位于某个线段上时&#xff0c;光标会变成手的形状。然后您可以单击并拖动来移动该线段。当鼠标位于线段的终点上时&#xff0c;光标会变成箭头。然后您可以单击并拖动以移动终点。当鼠…

Jenkins容器使用宿主机Docker(五)

DevOps之安装和配置 Jenkins (一) DevOps 之 CI/CD入门操作 (二) Sonar Qube介绍和安装&#xff08;三&#xff09; Harbor镜像仓库介绍&安装 &#xff08;四&#xff09; Jenkins容器使用宿主机Docker&#xff08;五&#xff09; Jenkins流水线初体验&#xff08;六&#…