适配器模式:类适配器与对象适配器
适配器模式是一种结构性设计模式,旨在将一个接口转换成客户端所期望的另一种接口。它通常用于解决由于接口不兼容而导致的类之间的通信问题。适配器模式主要有两种实现方式:类适配器和对象适配器。下面,我们将详细探讨这两种方式的优缺点及适用场景,并说明在日常开发中适配器模式的常见应用。

1. 类适配器(Class Adapter)
定义
类适配器通过继承源类来实现目标接口。在这种情况下,适配器是目标接口的实现类,同时也是源类的子类。
优点
- 直接复用:能够直接复用源类的方法和属性。
- 简单直接:适合源类不需要被实例化的情况,易于实现。
缺点
- 多重继承问题:使用多重继承可能导致复杂性,特别是在源类为最终类时,无法被继承。
- 单一适配:每个适配器只能适配一个源类,灵活性不足。
运用场景
- 当需要将一个类的接口转化为客户端所需的接口,而源类的行为可以直接复用时,适合使用类适配器。
- 在构建一个小型应用程序或在一个简单场景中使用。
示例
interface Printer {void print(String text);
}class OldPrinter {public void printString(String text) {System.out.println("Printing: " + text);}
}class PrinterAdapter extends OldPrinter implements Printer {@Overridepublic void print(String text) {printString(text);}
}
2. 对象适配器(Object Adapter)
定义
对象适配器通过持有源类的实例来实现目标接口。在这种情况下,适配器不继承源类,而是通过构造函数引入源类的对象,并在实现目标接口的方法时调用源类的方法。
优点
- 灵活性:可以适配多个源类,只需创建不同的适配器。
- 低耦合:源类与适配器之间的耦合度较低,便于维护和扩展。
缺点
- 额外开销:需要持有源类的实例,可能会增加内存开销。
- 复杂性:实现可能相对复杂,尤其在适配多个源类时。
运用场景
- 当需要适配多个源类或源类的变化时,对象适配器更为合适。
- 在大型应用程序中,尤其是在需要动态绑定或变化频繁的场景中使用。
示例
interface Printer {void print(String text);
}class OldPrinter {public void printString(String text) {System.out.println("Printing: " + text);}
}class PrinterAdapter implements Printer {private OldPrinter oldPrinter;public PrinterAdapter(OldPrinter oldPrinter) {this.oldPrinter = oldPrinter;}@Overridepublic void print(String text) {oldPrinter.printString(text);}
}
适配器模式在日常开发中的应用
适配器模式在日常开发中非常常见,特别是在服务架构中。例如,serviceImpl 调用 mapper 的设计模式可以视为适配器模式的应用。我们来具体分析这个例子。
解释
-
目标接口
Service接口通常定义了对外提供的功能,表示了业务逻辑的抽象。 -
源类
Mapper接口或实现类负责与数据库进行交互,封装了具体的数据库操作。 -
适配器类
ServiceImpl类充当适配器,它实现了Service接口,并在内部调用Mapper的方法。通过ServiceImpl,客户端(如 Controller)能够调用业务逻辑,而不需要直接依赖于Mapper。
优点
- 解耦合:控制器与数据库交互的细节被封装在
ServiceImpl中,控制器只需要关注业务逻辑。 - 透明性:控制器不需要知道底层的数据访问实现,增强了系统的灵活性。
- 扩展性:如果将来需要修改数据访问逻辑或更换数据库,只需更改
Mapper的实现,而不需要修改控制器或服务接口。
示例
假设有以下结构:
// Service接口
public interface UserService {User getUserById(int id);
}// Mapper接口
public interface UserMapper {User findUserById(int id);
}// ServiceImpl实现
public class UserServiceImpl implements UserService {private UserMapper userMapper;public UserServiceImpl(UserMapper userMapper) {this.userMapper = userMapper;}@Overridepublic User getUserById(int id) {return userMapper.findUserById(id);}
}// Controller类
@RestController
public class UserController {private UserService userService;public UserController(UserService userService) {this.userService = userService;}@GetMapping("/user/{id}")public User getUser(@PathVariable int id) {return userService.getUserById(id);}
}
在这个示例中,UserServiceImpl 就是适配器,它实现了 UserService 接口,并通过调用 UserMapper 的方法来完成数据访问。这样确实符合适配器模式的特征。
总结
适配器模式的核心思想是提供一个兼容性接口,使得不兼容的接口之间能够顺利通信。在选择适配器的实现方式时,需要考虑具体的应用场景:
- 类适配器适合简单且不需适配多个源类的情况。
- 对象适配器更灵活,适用于需要适配多个源类或动态变化的情况。
通过合理使用适配器模式,可以显著提高系统的可维护性和扩展性,降低代码耦合度。在实际开发中,尤其是在服务架构中,适配器模式的应用可以帮助我们更好地组织代码结构,使得业务逻辑与数据访问之间的关系更加清晰。希望这篇博客能够帮助你更好地理解适配器模式及其应用!
相关文章:
适配器模式:类适配器与对象适配器
适配器模式是一种结构性设计模式,旨在将一个接口转换成客户端所期望的另一种接口。它通常用于解决由于接口不兼容而导致的类之间的通信问题。适配器模式主要有两种实现方式:类适配器和对象适配器。下面,我们将详细探讨这两种方式的优缺点及适…...
volatile原理
volatile原理 volatile的底层实现原理是内存屏障,Memory Barrier(Memory Fence) 对volatile变量的写指令后会加入写屏障 对volatile变量的读指令前会加入读屏障 如何保证可见性 写屏障保证在该屏障之前的,对共享变量的改动,都同步到主存当中 public void actor2(I_Resu…...
【AI神器】SD(Stable Diffusion)一键安装包
是否还在无法使用Stable Diffusion 而烦恼,今天就给大家带来sd的私有化部署,一键安装包 https://pan.quark.cn/s/c16aa752ac6a 当然对电脑配置略微有些要求: 首先,本地安装对电脑配置有一些基本要求, 本地电脑安装…...
lanqiaoOJ 1112:小王子双链表 ← STL list
【题目来源】https://www.lanqiao.cn/problems/1112/learning/【题目描述】 小王子有一天迷上了排队的游戏,桌子上有标号为 1-10 的 10 个玩具,现在小王子将他们排成一列,可小王子还是太小了,他不确定他到底想把那个玩具摆在哪里&…...
C#WPF之快速理解MVVM模式
MVVM是一种设计模式,特别适用于WPF等XAML-based的应用程序开发。MVVM模式主要包含三个部分:Model(模型)、View(视图)和ViewModel(视图模型)。 Model(模型)&a…...
微积分[1]|微积分的底层逻辑——解析几何、不等式与极限(含博主推荐的数理阅读教材共计21本书籍)
原创首发于CSDN,禁止转载,谢谢! 文章目录 微积分的底层逻辑探究一篇网络文章《数学分析的核心——不等式》高中数学与大学数学的脱节|脱节的实质含义|高中与大学的衔接数理书籍推荐 我个人所认为的数学分析的根基更新时…...
1-磁盘建立空闲分区
学习目标: 掌握磁盘分区的基本知识和操作技能,能够独立创建和管理磁盘空闲分区,以优化存储空间和提高系统性能,为后续的系统安装和数据管理打下基础。 学习内容: 1 选择一个适合的磁盘分区软件。推荐DiskGenius、Par…...
使用SearXNG-搭建个人搜索引擎(附国内可用Docker镜像源)
介绍 SearXNG是聚合了七十多种搜索服务的开源搜索工具。我们可以匿名浏览页面,不会被记录和追踪。作为开发者,SearXNG也提供了清晰的API接口以及完整的开发文档。 部署 我们可以很方便地使用Docker和Docker compose部署SearXNG。下面给出Docker部署Se…...
InnoDB 存储引擎<五>undo log, redo log,以及双写缓冲区
目录 撤销⽇志 - Undo Log 双写缓冲区 - Doublewrite Buffer 重做⽇志 - Redo Log 本篇是继承自上篇InnoDB存储引擎的磁盘文件 上篇链接:InnoDB 存储引擎<四>磁盘文件一 撤销⽇志 - Undo Log 1.什么是撤销⽇志? 解答问题&a…...
Find My运动耳机|苹果Find My技术与耳机结合,智能防丢,全球定位
运动耳机是为运动时候佩带的耳机,而是一种区别于一般耳机的能稳定固定在佩戴部位的耳机,该种耳机不会因为身体运动而使耳机从耳朵里掉落,普遍带有防滴溅、轻便等特性,透气性能较好,属于开放式耳机。 在智能化加持下&…...
书生大模型实战营Linux+InternStudio 关卡任务
一、端口映射 使用以下命令进行端口映射 ssh -p {YOUR_PORT} rootssh.intern-ai.org.cn -CNg -L 7860:127.0.0.1:7860 -o StrictHostKeyCheckingno 命令解释: -p 37367:是指定 SSH 连接的端口为 37367。rootssh.intern-ai.org.cn:表示要以…...
研究实锤:别让大模型「想」太多,OpenAI o1准确率竟下降36.3%
思维链(CoT)已被证明可以在许多任务(如多步骤推理)上显著提升大模型的性能。然而,在哪些情况下,CoT 会系统性地降低大模型的性能,这仍然是一个有待进一步讨论的问题。 如今,来自普林…...
C++游戏开发
C游戏开发概述 C 是游戏开发中的主要编程语言之一,因其性能、控制和广泛的生态系统而受到开发者的青睐。随着游戏行业的迅速发展,C 被用来构建许多成功的游戏和游戏引擎。本文将深入探讨 C 在游戏开发中的应用,包括基础概念、技术栈、示例代…...
ChatGPT中的RAG;大模型微调;通过正确的提问和回答数据进行问答系统的微调;
目录 ChatGPT中的RAG 1.检索器: 2.生成器: 3.结合使用: 大模型微调 通过正确的提问和回答数据进行问答系统的微调 ChatGPT中的RAG 在ChatGPT中,RAG(Retrieval-Augmented Generation)是一种结合了检索与生成的技术,旨在提高模型的回答质量和准确性。 RAG模型通常由两个…...
6款IntelliJ IDEA插件,让Spring和Java开发如虎添翼
文章目录 1、SonarLint2、JRebel for IntelliJ3、SwaggerHub插件4、Lombok插件5、RestfulTool插件6、 Json2Pojo插件7、结论 对于任何Spring Boot开发者来说,两个首要的目标是最大限度地提高工作效率和确保高质量代码。IntelliJ IDEA 是目前最广泛使用的集成开发环境…...
源代码加密解决方案:文档加密与沙盒加密的比较分析
源代码加密是保护企业知识产权和市场竞争力的关键手段。在众多源代码加密技术中,文档加密类软件和沙盒加密类软件SDC是两种重要的解决方案。以下是对这两种技术的分析: 文档加密类软件: 这类软件主要采用APIHOOK应用层透明加密技术࿰…...
Spring Boot 与 Vue 共筑高校网上订餐卓越平台
作者介绍:✌️大厂全栈码农|毕设实战开发,专注于大学生项目实战开发、讲解和毕业答疑辅导。 🍅获取源码联系方式请查看文末🍅 推荐订阅精彩专栏 👇🏻 避免错过下次更新 Springboot项目精选实战案例 更多项目…...
【数据仓库】Hive 拉链表实践
背景 拉链表是一种数据模型,主要是针对数据仓库设计中表存储数据的方式而定义的;顾名思义,所谓拉链表,就是记录历史。记录一个事务从开始一直到当前状态的所有变化的信息。 拉链表可以避免按每一天存储所有记录造成的海量存储问题…...
【python_pandas_将列表按照某几列进行分组,再求和,按照原列表的字段顺序返回】
说明: 1、按照[“行描述”,”‘公司代码’, ‘科目代码’, ‘预算项目代码’] 进行分组。 2、对“贷方”列进行求和。 3、最后按照之前的表头顺序进行排序,返回结果列表。 #-*- coding:utf-8-*import pandas as pd def consolidate_salary_provisions(l…...
Vue的双向绑定
Vue的双向绑定特性介绍 在现代前端开发中,数据的管理和UI的更新是至关重要的。Vue.js作为一个渐进式JavaScript框架,提供了强大的双向数据绑定机制,极大地简化了这些操作。在本文中,我们将深入探讨Vue的双向绑定特性。 什么是双…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
