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

结构型设计模式——适配器模式

适配器模式

这个更加好理解,就是做适配功能的类,例如,现在手机没有了圆形耳机接口,只有Type-C接口,因此你如果还想要使用圆形耳机的话需要买个圆形接口转Type-C的转换器(适配器),这就是所谓的适配器,将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

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

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

类适配器模式

适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。使用一个例子来说明类适配器模式,现有一台电脑只能读取SD卡,而要读取TF卡中的内容的话就需要使用到适配器。创建一个读卡器,将TF卡中的内容读取出来。

举个非常好理解的例子,就好比A是欧洲人,B是日本人,欧洲有个芯片公司只允许欧洲人外貌的人进入吃饭并学习芯片技术,此时日本人想要进去是不行的,会被门卫驱赶。这个时候B最好的方式就是找个适配器,也就是找一套人皮面具扮演成欧洲人就能进去,进去之后吃饭还是这个日本人吃,学习芯片技术也是这个日本人,只不过使用人皮面具蒙混过关而已。而下面是使用SDAdapterTF类 通过implements SDCard 来穿上人皮面具,以适配Computer类方法的参数类型(多态牛逼),而这个多态的运用就是这个人皮面具,而真正功能的实现还是要靠TFCardImpl来实现,而使用TFCardImpl又有两种方式,这里讲第一种通过继承的方式——类适配器模式。

类图如下:
在这里插入图片描述

代码

首先定义我们的电脑实体类、SD卡实体类和TF卡实体类,电脑类仅能读取SD卡,即参数只能传入SDCard的子类,如下:

// 定义Computer类
public class Computer {private String type;public String readSDCard(SDCard sdCard){if(sdCard==null){System.out.println("SD 卡损坏!");}return sdCard.readSD();}public void writeSDCard(SDCard sdCard,String msg){sdCard.writeSD(msg);}
}// 定义SDCard接口
public interface SDCard {String readSD();void writeSD(String msg);
}// 定义TFCard接口
public interface TFCard {String readTF();void writeTF(String msg);
}// SDCard的实现类
public class SDCardImpl implements SDCard{@Overridepublic String readSD() {return "SD卡读出内容:Hello World!";}@Overridepublic void writeSD(String msg) {System.out.println("SD卡写入内容:"+msg);}
}// TFCard的实现类
public class TFCardImpl implements TFCard{@Overridepublic String readTF() {return "TF卡读出内容:Hello World!";}@Overridepublic void writeTF(String msg) {System.out.println("TF卡写入内容:"+msg);}
}

接着定义适配器类,我们电脑只能接受SDCard的子类,而真正完成TF卡的读取功能的是得是TFCard的实现类TFCardImpl ,因此这个适配器应该完全具有TFCardImpl的所有功能,因此需要直接继承TFCardImpl即可,那么如何还要让适配器成为SDCard的子类呢?因为前面已经继承了一个类,因此后面我们使用实现方式实现SDCard接口成为SDCard的子类。这里废话一句:这里的SDCard就好比上面举例的欧洲人皮面具,TFCardImpl好比的是那个日本人。


public class SDAdapterTF extends TFCardImpl implements SDCard{// 特别注意:继承了实现类,实现了SDCard的接口@Overridepublic String readSD() {return super.readTF(); // 调用继承的父类TFCardImpl的方法}@Overridepublic void writeSD(String msg) {super.writeTF(msg); // 调用继承的父类TFCardImpl的方法}
}

客户端测试:

public class Main {public static void main(String[] args) {Computer computer = new Computer();// 对于SD卡是可以直接读取的SDCardImpl sdCard = new SDCardImpl();String msg = computer.readSDCard(sdCard);System.out.println(msg);computer.writeSDCard(sdCard,"你好,世界!");//        对于TF卡,不能直接读取,而要借助适配器来调用TF实现类的方法
//        TFCardImpl tfCard = new TFCardImpl();
//        computer.readSDCard(tfCard)SDAdapterTF sdAdapterTF = new SDAdapterTF();msg = computer.readSDCard(sdAdapterTF);System.out.println(msg);computer.writeSDCard(sdAdapterTF,"你好世界!");}
}

输出:

SD卡读出内容:Hello World!
SD卡写入内容:你好,世界!
TF卡读出内容:Hello World!
TF卡写入内容:你好世界!

可以看到,上述适配器SDAdapterTF实际上就是读卡器嘛!只不过我们的电脑只能接受SD卡的插口,SDAdapterTF扮演的就是TF转SD接口的读卡器。因此其实是让SDAdapterTF继承了TFCardImple,因此可以在里面直接调用TFCardImple的方法,而SDAdapterTF由是SDCard的接口实现类,因此也可以传入到Computer的被读取,多态是面向对象的灵魂!!!超级灵活!

缺点: 类适配器模式违背了合成复用原则。类适配器是客户类有一个接口规范的情况下可用,反之不可用。那么,这时你可能已经想到了,我可以不继承TFCardImple吗?直接传入TFCardImpl不就好了吗,是的,这种模式非常接近我们的日常生活。也就是下面要讲的对象适配器模式。

对象适配器模式

紧接着上面使用的是继承实现,这里我们讲解第二种实现方式,通过构造器方法传递TFCardImpl对象来实现,实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。我们使用对象适配器模式将读卡器的案例进行改写。类图如下:

在这里插入图片描述

代码

这里只是需要修改一下适配器就行,如果不继承TFCardImpl 还想要调用它的方法应该如何做呢?很简单,让TFCardImpl 的对象作为参数传进来就行,如下:

public class SDAdapterTF implements SDCard {private TFCard tfCard;public SDAdapterTF(TFCard tfCard){this.tfCard = tfCard;}@Overridepublic String readSD() {return tfCard.readTF();}@Overridepublic void writeSD(String msg) {tfCard.writeTF(msg);}
}

客户端测试:

public class Main {public static void main(String[] args) {Computer computer = new Computer();// 对于SD卡是可以直接读取的SDCardImpl sdCard = new SDCardImpl();String msg = computer.readSDCard(sdCard);System.out.println(msg);computer.writeSDCard(sdCard,"你好,世界!");// 对于TF卡需要是有适配器类读取TFCard tfCard = new TFCardImpl();SDAdapterTF sdAdapterTF = new SDAdapterTF(tfCard);msg = computer.readSDCard(sdAdapterTF);System.out.println(msg);computer.writeSDCard(sdAdapterTF,"你好世界!");}
}

输出:

SD卡读出内容:Hello World!
SD卡写入内容:你好,世界!
TF卡读出内容:Hello World!
TF卡写入内容:你好世界!

对象适配器模式其实更加贴近我们的直觉,一般我们将TF卡使用读卡器插入到电脑,而这里的SDAdapterTF对象就是 读卡器+TF 卡,只不过类适配器模式将TFCardImpl直接继承了,相当于焊丝了。而我们的对象适配器模式获取到TFCardImpl是通过构造方法获取到的,更加灵活!因此总结来说,类适配器直接继承,而对象适配器通过构造方法获取对象,仅此而已!

注意:还有一个适配器模式是接口适配器模式。当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可。

使用场景: 如果两个类做同一件事(例如本题的存储卡,都是完成数据存取功能的,还比如读取不同编码文件的类)即我有的方法你也要有,只不过各自的方法具体做的不一样,方法中的有些细节不同,可以使用适配器屏蔽掉接口类型的不一致性。

参考内容

传智播客设计模式相关笔记(主要)
https://zhuanlan.zhihu.com/p/369272002

相关文章:

结构型设计模式——适配器模式

适配器模式 这个更加好理解,就是做适配功能的类,例如,现在手机没有了圆形耳机接口,只有Type-C接口,因此你如果还想要使用圆形耳机的话需要买个圆形接口转Type-C的转换器(适配器),这…...

三菱FX系列PLC定长切割控制(线缆裁切)

三菱PLC绝对定位指令DDRVA实现往复运动控制详细介绍请查看下面文章链接: https://rxxw-control.blog.csdn.net/article/details/135570157https://rxxw-control.blog.csdn.net/article/details/135570157这篇博客我们介绍线缆行业的定长切割控制相关算法。 未完待…...

GPT编程:运行第一个聊天程序

环境搭建 很多机器学习框架和类库都是使用Python编写的,OpenAI提供的很多例子也是Python编写的,所以为了方便学习,我们这个教程也使用Python。 Python环境搭建 Python环境搭建有很多种方法,我们这里需要使用 Python 3.10 的环境…...

NLP论文阅读记录 - WOS | ROUGE-SEM:使用ROUGE结合语义更好地评估摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结 前言 ROUGE-SEM: Better evaluation of summarization using ROUGE combin…...

vscode 创建文件自动添加注释信息

随机记录 目录 1. 背景介绍 2. "Docstring Generator"扩展 2.1 安装 2.2 设置注释信息 3. 自动配置py 文件头注释 1. 背景介绍 在VS Code中,您可以使用扩展来为新创建的Python文件自动添加头部注释信息。有几个常用的扩展可以实现此功能&#xff0…...

JVM内存区域详解,一文弄懂JVM内存【内存分布、回收算法、垃圾回收器】

视频讲解地址 学习文档 一、内存区域 区域描述线程私有如何溢出程序计数器为了线程切换后能恢复到正确的执行位置,每个线程都要有一个独立的程序计数器。✅唯一一个不会内存溢出的地方虚拟机栈1. 每个方法执行的时候,Java虚拟机都会同步创建一个栈帧用于…...

uniapp搜索附近蓝牙信标(iBeacon)

一、 iBeacon介绍 iBeacon是苹果在2013年WWDC上推出一项基于蓝牙4.0(Bluetooth LE | BLE | Bluetooth Smart)的精准微定位技术,在iPhone 4S后支持。当你的手持设备靠近一个Beacon基站时,设备就能够感应到Beacon信号,范…...

Redis 常见数据结构以及使用场景分析

Java面试题目录 Redis 常见数据类型以及使用场景分析 Redis中有string、list、hash、set、sorted set、bitmap这6种数据类型。 string可以用来做缓存,分布式锁,计数器等。 list可以实现消息队列,分页查询等。 hash适合存储对象结构。 set 可…...

LMDeploy 大模型量化部署实践

LMDeploy 大模型量化部署实践 大模型部署背景模型部署定义产品形态计算设备 大模型特点大模型挑战大模型部署方案 LMDeploy简介推理性能核心功能-量化核心功能-推理引擎TurboMind核心功能 推理服务 api-server 案例(安装、部署、量化) 大模型部署背景 模型部署 定义 将训练好…...

15个为你的品牌增加曝光的维基百科推广方法-华媒舍

维基百科是全球最大的免费在线百科全书,拥有庞大的用户群体和高质量的内容。在如今竞争激烈的市场中,利用维基百科推广品牌和增加曝光度已成为许多企业的重要策略。本文将介绍15种方法,帮助你有效地利用维基百科推广品牌,提升曝光…...

启动redis出现Creating Server TCP listening socket 127.0.0.1:6379: bind: No error异常

1.进入redis安装目录,地址栏输入cmd 2.输入命令 redis-server.exe redis.windows.conf redis启动失败 解决,输入命令 #第一步 redis-cli.exe#第二步 shutdown#第三步 exit第四步 redis-server.exe redis.windows.conf 显示以下图标即成功...

响应式编程Reactor优化Callback回调地狱

1. Reactor是什么 Reactor 是一个基于Reactive Streams规范的响应式编程框架。它提供了一组用于构建异步、事件驱动、响应式应用程序的工具和库。Reactor 的核心是 Flux(表示一个包含零到多个元素的异步序列)和 Mono表示一个包含零或一个元素的异步序列…...

React项目实战--------极客园项目PC端

项目介绍:主要将学习到的项目内容进行总结(有需要项目源码的可以私信我) 关于我的项目的配置如下,请注意下载的每个版本不一样,写的api也不一样 一、项目介绍 1.资料 1)短信接收&M端演示&#xff1a…...

Jerry每次能向前或向后走n*n步(始终不能超过初始位置1e5),q(q <= 1e5)次询问,求向前走d最少要几次

题目 思路&#xff1a;因为有走的过程不能超初始位置1e5的限制&#xff0c;所以不能直接用奇数最多两次&#xff0c;4的倍数最多两次的结论。spfa&#xff0c;平方数的dis为1&#xff0c;然后推出其他数的dis #include<bits/stdc.h> using namespace std; #define int …...

【Spring Boot 3】【Flyway】数据库版本管理

【Spring Boot 3】【Flyway】数据库版本管理 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是…...

蓝桥杯基础数据结构(java版)

引言 数据结构数据结构。所以数据结构是一个抽象的概念。其目的是为了更好的组织数据方便数据存储。下面我们来看一些简单的数据储存方式 输入和输出 这里先介绍java的输入和输出。简单引入&#xff0c;不过多详细介绍&#xff0c;等我单一写一篇的时候这里会挂上链接 简单的…...

39 C++ 模版中的参数如果 是 vector,list等集合类型如何处理呢?

在前面写的例子中&#xff0c;模版参数一般都是 int&#xff0c;或者一个类Teacher&#xff0c;假设我们现在有个需求&#xff1a;模版的参数要是vector&#xff0c;list这种结合类型应该怎么写呢&#xff1f; //当模版中的类型是 vector &#xff0c;list 等集合类型的时候的处…...

5.Pytorch模型单机多GPU训练原理与实现

文章目录 Pytorch的单机多GPU训练1)多GPU训练介绍2)pytorch中使用单机多GPU训练DistributedDataParallel(DDP)相关变量及含义a)初始化b)数据准备c)模型准备d)清理e)运行 3)使用DistributedDataParallel训练模型的一个简单实例 欢迎访问个人网络日志&#x1f339;&#x1f339;知…...

想成为一名C++开发工程师,需要具备哪些条件?

C语言是一门面向过程的、抽象化的通用程序设计语言&#xff0c;广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能&#xff0c;但仍然保…...

Qat++,轻量级开源C++ Web框架

目录 一.简介 二.编译Oat 1.环境 2.编译/安装 三.试用 1.创建一个 CMake 项目 2.自定义客户端请求响应 3.将请求Router到服务器 4.用浏览器验证 一.简介 Oat是一个面向C的现代Web框架 官网地址&#xff1a;https://oatpp.io github地址&#xff1a;https://github.co…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

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 …...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...