当前位置: 首页 > news >正文

关于适配器模式,我遗漏了什么

近期有些tasks需要 重构or适配 老的代码。

与其向上面堆💩,不如优雅的去解决。

首先我的问题在于,错误的把 堆屎的操作 ,当作了适配器模式的操作。

比如原函数入参,需要更改某个属性,把这种操作外包一层套进去,就是堆屎。

适配器模式的重点在于:适配器实现目标接口,并且持有适配者的实例

做法是:转换一个接口到另一个接口。(这个经常和外观模式搞混)

实际工作中尝试使用虚方法去实现,让前端的调用为被转换过的接口。

虚方法:

1、virtual方法表示此方法可以被重写, 也就是说这个方法具有多态.父类中的方法是通用方法,可以在子类中重写以重新规定方法逻辑.

2、virtual方法可以直接使用,和普通方法一样

3、不是必须重写的. 子类可以使用base.方法 的方式调用, 无论有没有在子类使用override去重写

virtual关键字只是明确标示此方法可以被重写, 其实它和一般的方法没有什么区别

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

但是我偏要用类适配器!

类适配器

类适配器:适配器继承适配对象,并实现适配目标的所有方法

public interface EuropeSocket {/** 欧式三叉 通电 接通电 插座*/String useEuropesocket();
}// 欧式三叉实现类
public class EuropeSocketImpl implements EuropeSocket {@Overridepublic String useEuropesocket() {String msg ="使用欧式三叉充电";return msg;}
}
public interface ChineseSocket {/*** 使用中国双叉充电* @return*/String useChineseSocket();
}// 中国插头的实现类
public class ChineseSocketImpl implements ChineseSocket {@Overridepublic String useChineseSocket() {String msg="使用中国双叉充电";return msg;}
}
/*** 定义适配器类 中国双叉转为欧洲三叉**/
public class ChineseAdapterEurope extends EuropeSocketImpl implements ChineseSocket {@Overridepublic String useChineseSocket() {System.out.println("使用转换器转换完成");return useEuropesocket();}
}

开始使用测试!

public class Computer {public String useChineseSocket(ChineseSocket chineseSocket) {if(chineseSocket == null) {throw new NullPointerException("sd card null");}return chineseSocket.useChineseSocket();}
}

提前注:父类声明子类实例化产生的对象使用的是子类从父类继承的方法和属性。 

父类声明子类实例化对象详解_扶公瑾以苏的博客-CSDN博客_c父类对象由子类实例化

public class Client {public static void main(String[] args) {Computer computer = new Computer();ChineseSocket chineseSocket = new ChineseSocketImpl();System.out.println(computer.useChineseSocket(chineseSocket));System.out.println("------------");ChineseAdapterEurope adapter = new ChineseAdapterEurope();System.out.println(computer.useChineseSocket(adapter));/*** 输出:* 使用中国双叉充电* ------------* 使用转换器转换完成* 使用欧式三叉充电*/}
}

对象适配器

实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口

题目还是和上面一样的哈。代码其实差异很小

目标(Target)接口:即图中的欧式三叉

public interface EuropeSocket {/** 欧式三叉 通电 接通电 插座*/String useEuropesocket();
}// 欧式三叉实现类
public class EuropeSocketImpl implements EuropeSocket {@Overridepublic String useEuropesocket() {String msg ="使用欧式三叉充电";return msg;}
}
复制代码

适配者(Adaptee):即中国双叉

public interface ChineseSocket {/*** 使用中国双叉充电* @return*/String useChineseSocket();
}// 中国插头的实现类
public class ChineseSocketImpl implements ChineseSocket {@Overridepublic String useChineseSocket() {String msg="使用中国双叉充电";return msg;}
}
复制代码

适配器(Adapter)类: 就是这个适配器内做了一些更改 从继承改为了成员变量的方式

public class ChineseAdapterEurope implements ChineseSocket {private EuropeSocket europeSocket;public ChineseAdapterEurope(EuropeSocket europeSocket) {this.europeSocket = europeSocket;}@Overridepublic String useChineseSocket() {System.out.println("使用转换器转换完成");return europeSocket.useEuropesocket();}
}
复制代码

电脑类

public class Computer {public String useChineseSocket(ChineseSocket chineseSocket) {if(chineseSocket == null) {throw new NullPointerException("sd card null");}return chineseSocket.useChineseSocket();}
}
复制代码

测试:

public class Client {public static void main(String[] args) {Computer computer = new Computer();ChineseSocket chineseSocket = new ChineseSocketImpl();System.out.println(computer.useChineseSocket(chineseSocket));System.out.println("------------");//这里做了更改EuropeSocket europeSocket=new EuropeSocketImpl();ChineseAdapterEurope adapter = new ChineseAdapterEurope(europeSocket);System.out.println(computer.useChineseSocket(adapter));/*** 输出:* 使用中国双叉充电* ------------* 使用转换器转换完成* 使用欧式三叉充电*/}
}

适合于解决问题常见:

  •  需要的东西有,但不能用,且短时间无法改造。即,使得一个功能适合不同的环境。
  •   在开发中,系统的数据、行为都匹配,但接口不符时,可以考虑适配器。
  •   希望复用一些现存的类,但是接口又与复用环境的要求不一致,应该考虑用适配器模式。(使用一个已经存在的类,但它的接口(即,方法),与需要的不相同时)

2023/2/12

划重点:希望复用一些现存的类,但是接口又与复用环境的要求不一致,应该考虑用适配器模式。(使用一个已经存在的类,但它的接口(即,方法),与需要的不相同时)

这个正是我现在面临的问题。

总之,时间足够我就优雅的,完美的去建立一个可扩展性强的适配层。

如果催我。那我就堆堆乐 💩💩💩

references:

Java设计模式-适配器模式 理论代码相结合 - 掘金

相关文章:

关于适配器模式,我遗漏了什么

近期有些tasks需要 重构or适配 老的代码。 与其向上面堆💩,不如优雅的去解决。 首先我的问题在于,错误的把 堆屎的操作 ,当作了适配器模式的操作。 比如原函数入参,需要更改某个属性,把这种操作外包一层…...

SQL Serve 日志体系结构

SQL Server 事务日志记录着 undo 及 redo 日志,为了保证数据库在崩溃后恢复,或者在正常数据库操作期间进行回滚,保证数据库事务完整性和持久化。如果没有事务日志记录,数据库在事务上将不一致,并且在数据库崩溃后可能导…...

【C++1】函数重载,类和对象,引用,string类,vector容器,类继承和多态,/socket,进程信号,public,ooci

文章目录1.函数重载:writetofile(),Ctrue和false,C0和非02.类和对象:vprintf2.1 构造函数:对成员变量初始化2.2 析构函数:一个类只有一个,不允许被重载3.引用:C中&取地址&#x…...

asio网络编程 tcp、udp、rpc

轻量级的tcp/udp/rpc库,简化socket程序编写。 同时,RPC部分也提供了方便易用的功能。 仓库地址 https://github.com/shuai132/asio_net asio_net a Tiny Async TCP/UDP/RPC library based on ASIO and RpcCore Features 简化TCP、UDP相关程序的编写…...

双目测距------双目相机V1.0,将双目相机采集到任意一点的深度数据进行串口传输(带源码)

Depth2Uart 双目测距------双目相机V1.0,将双目相机采集到任意一点的深度数据进行串口传输 一、项目说明/Overview 所实现的功能:基于Intel Realsense官方提供的SDK,双目深度相机能获取到相机任何一个像素点距离前方障碍物的距离&#xff0…...

jetson nano(ubuntu)安装Cmake

文章目录安装环境一.命令行安装二.Cmake源码编译安装安装环境 jetson nano 系统:4.6.1 一.命令行安装 sudo apt install cmake这种直接安装cmake的方式,其实安装的版本都太老了,这种方式不推荐 二.Cmake源码编译安装 更新一下系统软件 su…...

图的基本介绍和表示方式

图的基本介绍 为什么要有图这个基本数据结构? 我们还学习过线性表(数组、队列、链表和栈)和树,但是我们可以发现,线性表局限于一个直接前驱(就是只能有唯一一个前面的结点)和一个直接后继的(…...

本周大新闻|传微软解散工业元宇宙团队,MIT研发垂直堆叠全彩Micro LED

本周大新闻,AR方面,消息称微软解散工业元宇宙团队;德国AR公司Gixel GmbH亮相;Brilliant推出单片式附加形态AR眼镜;MIT研发垂直堆叠全彩Micro LED;谷歌XR串流正式上线。VR方面,索尼发布了PS VR2的…...

SpringMVC:拦截器(12)

拦截器1. 拦截器概念2. 拦截器入门案例2.1 环境准备2.2 拦截器开发步骤1: 创建拦截器类步骤2: 配置拦截器类步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描步骤4: 简化SpringMvcSupport的编写5 测试3. 拦截器参数解析(了解)3.1 前置处理…...

计算机网络3:HTTP1.0和HTTP1.1的区别

目录1. HTTP是什么2.HTTP1.0和HTTP1.1的区别3.名词解释(1)If-Modified-Since(IMS)、Expires(2)If-None-Match,Etag(3)If-Unmodified-Since1. HTTP是什么 超文本传输协议…...

Urho3D 编辑器说明

Urho3D编辑器是一个脚本应用程序,可以与Urho3D播放器应用程序一起运行。要开始,请执行以下任意命令:(在bin目录中)Editor.bat、Editor.sh或Urho3DPlayer Scripts/Editor.as Urho3D播放器应用程序支持的所有命令行选项…...

C++类基础(十一)

运算符重载&#xff08;二&#xff09; ● 对称运算符通常定义为非成员函数以支持首个操作数的类型转换 struct Str {int val 0;Str(int input): val(input){}auto operator(Str x){std::cout << "auto operator(Str x)\n";return Str(val x.val);} }; int …...

Windows安装系列:SVN Server服务

一、下载与安装 1、下载VisualSVN-Server-5.1.1-x64.msi 地址&#xff1a;Download | VisualSVN Server 2、找到最新版本SVN 5.1.1&#xff0c;直接双击它&#xff0c;弹出如下安装界面 3、点击Next 4、勾选我接受&#xff0c; 点击"Next" 5、默认选项&#xff0c…...

快速傅里叶算法(FFT)快在哪里?

目录 前言 1、DFT算法 2、FFT算法 2.1 分类 2.2 以基2 DIT&#xff08;时间抽取&#xff09; FFT 算法为例 2.2.1 一次分解 2.2.2 多次分解 参考 前言 对信号分析的过程中&#xff0c;为了能换一个角度观察问题&#xff0c;很多时候需要把时域信号波形变换到频域进行分…...

利用Markdown写学术论文资料汇总贴

1是最详细的&#xff0c;重点看&#xff01; Markdown 写作&#xff0c;Pandoc 转换&#xff1a;我的纯文本学术写作流程 2补充一些细节&#xff0c;也可以看看。 用Markdown写作学术论文 3写得和上面差不多&#xff0c;如果上面两篇有什么问题还没解决&#xff0c;可以看看…...

MySQL 高级查询

目录1.左关联2.右关联3.子查询4.联合查询5.分组查询1.左关联 MySQL中的左关联&#xff08;Left Join&#xff09;是一种基于共同列的连接操作&#xff0c; 它将左侧表中的所有行与右侧表中匹配的行结合在一起&#xff0c; 如果右侧表中没有匹配的行&#xff0c;则结果集中右侧…...

JavaSE学习day4_01 循环for,while,do...while

1. 循环高级 1.1 无限循环 for、while、do...while都有无限循环的写法。 最为常用的是while格式的。 因为无限循环是不知道循环次数的&#xff0c;所以用while格式的 代码示例&#xff1a; while(true){} 1.2 跳转控制语句&#xff08;掌握&#xff09; 跳转控制语句&…...

C/C++中的static关键字

概述在C/C中都有static关键字的使用&#xff0c;可以分别修饰变量和函数&#xff0c;分为静态变量【静态成员】、静态成员函数。2. static用法概况静态变量的作用范围在一个文件内&#xff0c;程序开始时分配空间&#xff0c;结束时释放空间&#xff0c;默认初始化为0&#xff…...

67 自注意力【动手学深度学习v2】

67 自注意力【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV19o4y1m7mo/?spm_id_fromautoNext&vd_source75dce036dc8244310435eaf03de4e330 给定长为n 的序列&#xff0c;每个xi为长为d的向量&#xff0c;自注意力将xi 既当…...

电子学会2022年12月青少年软件编程(图形化)等级考试试卷(二级)答案解析

青少年软件编程&#xff08;图形化&#xff09;等级考试试卷&#xff08;二级&#xff09; 一、单选题(共25题&#xff0c;共50分) 1. 一个骰子&#xff0c;从3个不同角度看过去的点数如图所示&#xff0c;请问5的对面是什么点数&#xff1f;&#xff08; &#xff09; …...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...