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

设计模式-适配器模式(Adapter)

设计模式-适配器模式(Adapter)

    • 一、适配器模式概述
      • 1.1 什么是适配器模式
      • 1.2 简单实现适配器模式
      • 1.3 使用适配器模式注意事项
    • 二、适配器模式的用途
    • 三、实现适配器模式的方式
      • 3.1 继承适配器模式(Inheritance Adapter)
      • 3.2 组合适配器模式(Composition Adapter)
      • 3.3 装饰器适配器模式(Decorator Adapter)
      • 3.4 代理适配器模式(Proxy Adapter)

一、适配器模式概述

1.1 什么是适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,它主要用于解决两个不兼容的接口之间的问题。这种模式通过结合两个独立接口的功能,使原本不能一起工作的那些类可以一起工作。

适配器模式涉及到一个单一的类,这个类负责将独立的或不兼容的接口功能整合到一起。举个例子,读卡器就是作为内存卡和笔记本之间的适配器。我们先把内存卡插入读卡器,再把读卡器插入笔记本,然后就可以通过笔记本来读取内存卡的内容了。

适配器模式也被称为Wrapper(包装器),因为它主要是将目标类用一个新类包装一下,即在客户端与目标类之间加了一层。这解决了现存的类提供的接口与我们系统的接口不兼容,而我们还不能修改现存类的问题。

1.2 简单实现适配器模式

首先,我们定义一个目标接口Target:

public interface Target {void request();
}

然后,我们创建一个实现了Target接口的具体类ConcreteTarget:

public class ConcreteTarget implements Target {@Overridepublic void request() {System.out.println("ConcreteTarget 的 request 方法被调用");}
}

接下来,我们创建一个需要适配的接口Adaptee:

public interface Adaptee {void specificRequest();
}

然后,我们创建一个实现了Adaptee接口的具体类ConcreteAdaptee:

public class ConcreteAdaptee implements Adaptee {@Overridepublic void specificRequest() {System.out.println("ConcreteAdaptee 的 specificRequest 方法被调用");}
}

现在,我们需要创建一个适配器类Adapter,它也实现了Target接口,并包含一个Adaptee类型的成员变量。在Adapter类的request方法中,我们将调用Adaptee的specificRequest方法:

public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {System.out.println("Adapter 的 request 方法被调用");adaptee.specificRequest();}
}

最后,我们在客户端代码中使用适配器模式:

public class Client {public static void main(String[] args) {Adaptee adaptee = new ConcreteAdaptee();Target target = new Adapter(adaptee);target.request();}
}

运行客户端代码,输出结果如下:

Adapter 的 request 方法被调用
ConcreteAdaptee 的 specificRequest 方法被调用

1.3 使用适配器模式注意事项

在使用适配器模式时,需要注意以下几点:

  • 1、适配器模式主要解决现有接口无法改变的问题。也就是说,适配器不是在详细设计阶段添加的,而是在解决正在运行的项目问题时使用的。

  • 2、由于Java是单继承机制,类适配器需要继承src类,这一点算是一个缺点。因为这意味着目标类必须是接口,这就给设计带来了一定的局限性。

  • 3、src类的方法在Adapter中都会暴露出来,这可能会增加使用的成本。

  • 4、尽管适配器模式可以解决一些兼容性问题,但如果没有合理使用,可能会导致系统复杂性增加。因此,在使用时需要权衡利弊,尽量避免过度使用。

  • 5、当适配器的任何方法被调用时,它会将参数转换为合适的格式,然后将调用定向到其封装对象中的一个或多个方法。因此,正确实现适配器模式对于保证代码的稳定运行至关重要。

二、适配器模式的用途

适配器模式主要应用于解决系统需要使用现有类,但这些类的接口不符合系统的需要,即接口不兼容的问题。以下是一些具体的应用场景:

  • 1、系统需要使用现有的类,而此类的接口不符合系统的需要,即接口不兼容。例如,你可能需要将一个现有的类(如某个第三方库中的类)与你自己的代码一起使用,但这个现有类的接口与你所需要的接口不匹配。这时,你可以创建一个适配器类,将现有的类适配到你所需要的接口。

  • 2、如果你想建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。例如,你可能需要开发一个通用的数据处理模块,该模块应该能够处理多种不同类型的数据源(如数据库、文件、网络等)。这时,你可以创建一个适配器类,将不同的数据源适配到你的数据处理模块所期望的接口。

  • 3、需要一个统一的输出接口,而输入端的类型不可预知。例如,你可能需要编写一个函数,该函数接受一个对象作为参数,并调用该对象的某个方法。但是,该方法的参数类型和返回值类型可能有很多种可能性。这时,你可以创建一个适配器类,将不同的参数类型和返回值类型适配到你所需要的接口。

  • 4、当需增加客户端与目标类之间的抽象层以控制对目标类的访问。这种情况下,适配器模式可以为客户端提供一个与目标类更为友好的接口。

三、实现适配器模式的方式

3.1 继承适配器模式(Inheritance Adapter)

通过继承原有的类,实现适配器功能。这种方式适用于接口不兼容的情况,但需要修改原有类的代码。

public class Adaptee {public void specificRequest() {System.out.println("Adaptee specific request");}
}public class Adapter extends Adaptee {@Overridepublic void request() {super.specificRequest();}
}

3.2 组合适配器模式(Composition Adapter)

通过组合的方式实现适配器功能。这种方式适用于接口不兼容的情况,且不需要修改原有类的代码。

public interface Target {void request();
}public class Adaptee {public void specificRequest() {System.out.println("Adaptee specific request");}
}public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}

3.3 装饰器适配器模式(Decorator Adapter)

通过装饰器模式实现适配器功能。这种方式适用于接口不兼容的情况,且不需要修改原有类的代码。

public interface Target {void request();
}public class Adaptee {public void specificRequest() {System.out.println("Adaptee specific request");}
}public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}

3.4 代理适配器模式(Proxy Adapter)

通过代理模式实现适配器功能。这种方式适用于接口不兼容的情况,且不需要修改原有类的代码。

public interface Target {void request();
}public class Adaptee {public void specificRequest() {System.out.println("Adaptee specific request");}
}public class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}

相关文章:

设计模式-适配器模式(Adapter)

设计模式-适配器模式(Adapter) 一、适配器模式概述1.1 什么是适配器模式1.2 简单实现适配器模式1.3 使用适配器模式注意事项 二、适配器模式的用途三、实现适配器模式的方式3.1 继承适配器模式(Inheritance Adapter)3.2 组合适配器…...

react:创建项目

一: 使用create-react-app // 默认创建reactjs的webpack打包项目 npm i create-react-app -g create-react-app 项目名// 创建ts项目打包项目 sudo npx create-react-app my-app --template typescript 二: 使用vite npm create vitelatest // 创建react…...

RabbitMQ集群

RabbitMQ概述 1.RabbiMQ简介 RabbiMQ是⽤Erang开发的,集群⾮常⽅便,因为Erlang天⽣就是⼀⻔分布式语⾔,但其本身并不⽀持负载均衡。支持高并发,支持可扩展。支持AJAX,持久化,用于在分布式系统中存储转发消…...

Qt QtCreator调试Qt源码配置

目录 前言1、编译debug版Qt2、QtCreator配置3、调试测试4、总结 前言 本篇主要介绍了在麒麟V10系统下,如何编译debug版qt,并通过配置QtCreator实现调试Qt源码的目的。通过调试源码,我们可以对Qt框架的运行机制进一步深入了解,同时…...

JavaScript如何实现钟表效果,时分秒针指向当前时间,并显示当前年月日,及2024春节倒计时,源码奉上

本篇有运用jQuery&#xff0c;记得引入jQuery库&#xff0c;否则不会执行的喔~ <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> <meta name"chenc" content"Runoob"> <met…...

重生奇迹MU套装大全中的极品属性

在重生奇迹MU之中&#xff0c;你不能如其他游戏一般只看攻击与防御&#xff0c;你更要看属性&#xff0c;这才是重生奇迹中的王道&#xff01;属性好&#xff0c;才是极品&#xff0c;属性不佳&#xff0c;即便攻击、防御再出色&#xff0c;也只能沦落成为一件替用品&#xff0…...

用Python解决猴子分桃问题

1 问题 海滩上有一堆桃子&#xff0c;五只猴子来分。第一只猴子把这堆桃子平均分为五份&#xff0c;多了一个&#xff0c;这只猴子把多的一个扔入海中&#xff0c;拿走了一份。第二只猴子把剩下的桃子又平均分成五份&#xff0c;又多了一个&#xff0c;它同样把多的一个扔入海中…...

YOLOv8-Seg改进:分割注意力系列篇 | 新型的多尺度卷积注意力(MSCA)模块

🚀🚀🚀本文改进: 新型的多尺度卷积注意力(MSCA)模块,实现创新,MSCA包含三个部分:深度卷积聚合局部信息,多分支深度条卷积捕获多尺度上下文,以及11卷积建模不同通道之间的关系。 🚀🚀🚀MSCA多尺度特性在小目标分割检测领域表现优异 🚀🚀🚀YOLOv8-seg…...

基于springboot实现致远汽车租赁平台管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现致远汽车租赁平台管理系统演示 摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统…...

真的设计师做图只需要一个炫云客户端就够了

真的设计师做图只需要一个炫云客户端就够了&#xff0c;为什么这么说呢&#xff1f;因为炫云的这个客户端功能真的太全了&#xff0c;设计师想要的功能在炫云客户端上都有&#xff0c;而且还很多功能是免费的&#xff0c;非常的实用&#xff0c;具体有哪些功能我们一起来看看吧…...

简述 HTTP 请求的过程是什么?

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;请求的过程可以简单地描述为客户端与服务器之间的通信交互。下面是一般的 HTTP 请求过程&#xff1a; 解析 URL&#xff1a;客户端解析目标 URL&#xff0c;提取出服务器的主机名&#xff08;域名&#xff09;和端口号…...

免root修改手机imei的技术原理是什么?如何实现的?hook吗

在过去&#xff0c;修改手机IMEI&#xff08;International Mobile Equipment Identity&#xff09;通常需要Root权限&#xff0c;这给用户带来了一些不便&#xff0c;也存在一定的安全风险。然而&#xff0c;近年来&#xff0c;一些技术爱好者提出了一种免Root修改手机IMEI的方…...

【Redis】整合使用,进行注解式开发及应用场景和击穿、穿透、雪崩的讲解

目录 一、整合 1. 为什么 2. 整合应用 ( 1 ) pom配置 ( 2 ) 所需配置 3. 注解式开发及应用场景 1. Cacheable 2. CachePut 3. CacheEvict 4. 击穿、穿透、雪崩 一、整合 1. 为什么 Redis可以与SSM项目整合&#xff0c;主要是为了提高项目的性能和效率。以下是整合Re…...

数据分析-numpy

numpy numpy numpy简介优点下载ndarray的属性输出数据类型routines 函数ndarray对象的读写操作ndarray的级联和切分级联切分 ndarray的基本运算广播机制&#xff08;Broadcast&#xff09;ndarry的聚合操作数组元素的操作numpy 数学函数numpy 查找和排序 写在最后面 简介 nump…...

【Java】云HIS云端数字医院信息平台源码

一、云HIS系统特色 • 使用简易化 即开即用&#xff0c;快速复制&#xff0c;按需开通功能模块&#xff0c;多机构共享机房、软件、服务器、存储设备等资源&#xff0c;资源利用最大化。 • 连锁集团化 可支持连锁集团化管理&#xff0c;1N模式&#xff0c;支撑运营&#x…...

Jupyter Notebook 内核似乎挂掉了,它很快将自动重启

报错原因&#xff1a; OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized. OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade perfo…...

Flink -- 事件时间 Watermark

1、事件时间&#xff1a; 指的是数据产生的时间或是说是数据发生的时间。 在Flink中有三种时间分别是&#xff1a; Event Time&#xff1a;事件时间&#xff0c;数据产生的时间&#xff0c;可以反应数据真实发生的时间 Infestion Time&#xff1a;事件接收时间 Processing Tim…...

Django框架简介

文章目录 Django框架介绍MVC与MVT模型MVCMTV 版本问题运行django注意事项 Django的下载与基本命令下载Django方式一&#xff1a;在命令界面使用pip安装方式二&#xff1a;使用pycharm安装 Django的基础命令命令行操作pycharm操作 Django项目命令行操作与Pycharm操作的区别应用D…...

把wpf的窗体保存为png图片

昨晚在stack overflow刷问题时看到有这个问题&#xff0c;今天早上刚好来尝试学习一下 stack overflow的链接如下&#xff1a; c# - How to render a WPF UserControl to a bitmap without creating a window - Stack Overflow 测试步骤如下&#xff1a; 1 新建.net frame…...

2023NOIP A层联测28-大眼鸹猫

给你两个长度为 n n n 的序列 a , b a,b a,b&#xff0c;这两个序列都是单调不降的。 你可以对 a a a 进行不超过 m m m 次操作&#xff0c;每次操作你可以选择一个 i i i 满足 1 ≤ i ≤ n 1\le i\le n 1≤i≤n&#xff0c;然后选择一个整数&#xff08;可以是负数&…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...