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

适配器模式:类适配器与对象适配器

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

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 的设计模式可以视为适配器模式的应用。我们来具体分析这个例子。

解释
  1. 目标接口
    Service 接口通常定义了对外提供的功能,表示了业务逻辑的抽象。

  2. 源类
    Mapper 接口或实现类负责与数据库进行交互,封装了具体的数据库操作。

  3. 适配器类
    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应用层透明加密技术&#xff0…...

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的双向绑定特性。 什么是双…...

谷歌浏览器安装 Vue.js devtools 插件

文章目录 1. 安装2. 使用3. 注意 1. 安装 ① 搜索极简插件:https://chrome.zzzmh.cn/index ② 搜索框输入 Vue,选择 Vue.js devtools ③ 从历史版本里面选择并下载,选择 6.4 版本的就行 ④ 打开浏览器,右上角三个点 → 扩展程序…...

LWIP通信协议UDP发送、接收源码解析

1.UDP发送函数比较简短,带操作系统和裸机一样。以下是udp_sendto源码解析; 2.LWIP源码UDP接收数据 2.1.UDP带操作系统接收数据,以下是源码解析; 2.2.UDP裸机接收数据,以下是源码解析...

Linux—进程学习-01

目录 Linux—进程学习—11.冯诺依曼体系结构2.操作系统2.1操作系统的概念2.2操作系统的目的2.3如何理解管理2.4计算机软硬件体系的理解2.5系统调用和库函数的概念 3.进程3.1进程是什么3.2管理进程3.2.1描述进程-PCB3.2.2组织进程3.2.3总结 3.3查看进程 4.与进程有关的系统调用 …...

FR动态数据源插件支持配置模板中某个数据集进行数据连接的切换

1 需求背景 该插件的需求来源于官方帮助文档: 动态数据源/数据库- FineReport帮助文档 - 全面的报表使用教程和学习资料 官方的方案的缺点是会暴露数据库IP,端口密码等,不安全。...

epoll 技术为什么用rbtree而不用hashmap呢?

目录 1.epoll 技术为什么用rbtree而不用hashmap呢?2 .红黑树支持顺序遍历,这对于epoll的事件管理机制可能非常有用, 怎么理解 epoll 理解,可以参考这个 https://zhuanlan.zhihu.com/p/64746509 1.epoll 技术为什么用rbtree而不用…...

关于Android Studio Koala Feature Drop | 2024.1.2下载不了插件的解决办法

解决 androidStudio Settings->Plugins下载插件,点击install后没反应,同时插件描述相关显示不出来 第一步: 第二步: 点击设置,勾选Auto-detect proxy settings,输入网址 https://plugins.jetbrains.com…...

公共命名空间,2024年11月的笔记

进行类比思维。对于在电脑上显示字符的任务,需要字符集。曾经有人研究算法,希望编出一个神奇的程序,能够显示所有字符。但最终的结果是,需要字符集,人工地把所有字符收集起来,让电脑一个个记住,…...

登录功能设计(php+mysql)

一 登录功能 1. 创建一个登录页面(login.php),包含一个表单,用户输入用户名和密码。 2. 在表单的提交事件中,使用PHP代码处理用户输入的用户名和密码。 3. 首先,连接MySQL数据库。然后&a…...

从0开始学习Linux——远程连接工具

往期目录: 从0开始学习Linux——简介&安装 从0开始学习Linux——搭建属于自己的Linux虚拟机 从0开始学习Linux——文本编辑器 从0开始学习Linux——Yum工具 Linux 远程连接工具是指用于从远程计算机连接到 Linux 系统并进行操作的各种工具。它们可以帮助管理员或…...

Java线程6种生命周期及转换

多线程技术是我们后端工程师在面试的时候必问的一个知识点,今天就来盘点一下多线程的相关知识, 先来说下进程,线程及线程的生命周期: 进程:进程就是正在进行中的程序,是没有生命的实体,只有在运…...