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

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

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 的方法来完成数据访问。这样确实符合适配器模式的特征。

总结

适配器模式的核心思想是提供一个兼容性接口,使得不兼容的接口之间能够顺利通信。在选择适配器的实现方式时,需要考虑具体的应用场景:

  • 类适配器适合简单且不需适配多个源类的情况。
  • 对象适配器更灵活,适用于需要适配多个源类或动态变化的情况。

通过合理使用适配器模式,可以显著提高系统的可维护性和扩展性,降低代码耦合度。在实际开发中,尤其是在服务架构中,适配器模式的应用可以帮助我们更好地组织代码结构,使得业务逻辑与数据访问之间的关系更加清晰。希望这篇博客能够帮助你更好地理解适配器模式及其应用!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/884942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

语音识别:docker部署FunASR以及springboot集成funasr

内容摘选自: https://github.com/modelscope/FunASR/blob/main/runtime/docs/SDK_advanced_guide_offline_zh.md FunASR FunASR是一个基础语音识别工具包,提供多种功能,包括语音识别(ASR)、语音端点检测(VAD&#xf…

oracle-函数-NULLIF (expr1, expr2)的妙用

【语法】NULLIF (expr1, expr2) 【功能】expr1和expr2相等返回NULL,不相等返回expr1经典的使用场景: 1. 数据清洗与转换 在数据清洗过程中,NULLIF 函数可以用于将某些特定值(通常是无效或不需要的值)替换为 NULL&…

【LLM】Agentic Workflow的四种常见思路

note Reflection 和 Tool Use 属于比较经典且相对已经广泛使用的方式,Planning 和 Multi-agent 属于比较新颖比较有前景的方式。 文章目录 note一、四种设计模式1. Reflection2. Tool use3. Planning4. Multi-agent collaboration 二、相关代码实践 一、四种设计模…

Python数据可视化seaborn

产品经理在做数据分析时可能需要通过可视化来分析。seaborn官网 1. relplot 散点图 https://seaborn.pydata.org/examples/scatterplot_sizes.html import pandas as pd import seaborn as sns df pd.DataFrame({x: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],y: [8, 6, 7, 8, 4, 6,…

基于ssm的个人健康管理系统

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

CSS3新增渐变(线性渐变、径向渐变、重复渐变)

1.线性渐变 代码: 效果图: 使文字填充背景颜色: 效果图: 2.径向渐变 代码: 效果图: 代码图: 效果图: 3.重复渐变 代码: 效果图:

[mysql]mysql的DML数据操作语言增删改,以及新特性计算列,阿里巴巴开发手册mysql相关

1DML数据操作语言,增加删除改数据 插入数据INSERT 插入添加数据,两种方法 方式1:VALUES添加数据 #准备工作 USE atguigudb; CREATE TABLE IF NOT EXISTS emp1( id INT, name VARCHAR(15), hire_data DATE, salary DOUBLE(10,2)); SELECT * FROM emp1 INSERT INTO em…

自由学习记录(19)

unity核心也算是看完了吧,但觉得的确是少了点东西,之后再看mvc框架,和网络开发,,感觉有必要想想主次顺序了,毕竟在明年的3月之前尽量让自己更有贴合需求的能力 先了解一些相关概念,不用看懂&am…

vue计算属性

概念:基于现有的数据,计算出来新属性。并依赖数据的变化,自动重新计算 使用场景: 语法:声明在computed配置项中,一个计算属性对应一个函数,使用起来和普通属性一样使用{{计算属性名}} 代码&…

springboot2.x使用SSE方式代理或者转发其他流式接口

文章目录 1.需求描述2.代码2.1.示例controller2.2.示例service2.3.示例impl 3.测试 1.需求描述 使用SSE的方式主要还是要跟前端建立一个EventSource的链接,有了这个连接,然后往通道里写入数据流,前端自然会拿到流式数据,写啥拿啥…

Hive操作库、操作表及数据仓库的简单介绍

数据仓库和数据库 数据库和数仓区别 数据库与数据仓库的区别实际讲的是OLTP与OLAP的区别 操作型处理(数据库),叫联机事务处理OLTP(On-Line Transaction Processing),也可以称面向用户交易的处理系统,它是针对具体业务…

Ubuntu22.04 安装图形界面以及XRDP教程

一、准备环境 1.一台服务器安装系统ubuntu(这里大部分ubuntu系统可以同用) 2.安装的ubuntu系统未安装图形界面 二、操作步骤 1.远程ssh或者直接登录服务器命令行界面 ssh -p 远程端口 rootIP 2.更新系统软件包 sudo apt update # 更新本地的软件包…

C++:多态中的虚/纯虚函数,抽象类以及虚函数表

我们在平时,旅游或者是坐高铁或火车的时候。对学生票,军人票,普通票这些概念多少都有些许耳闻。而我们上篇文章也介绍过了继承与多继承。如果这些票我们都分别的去写一个类,当然很冗余,这里我们便可以去使用继承&#…

【易售校园二手平台】开源说明(包含项目介绍、界面展示与系列文章集合)

文章目录 仓库项目介绍技术架构界面登录界面首页闲置商品发布商品详情收藏页面消息页面私聊我的查看我发布的商品 可优化点开发讲解文章集合 仓库 🏠️ 项目仓库:易售校园二手平台gitee仓库 🌍️ 在线体验:易售校园二手平台&…

python怎么将字符串转换为数字

python如何将列表中的字符串转为数字?具体方法如下: 有一个数字字符的列表: numbers [1, 5, 10, 8] 想要把每个元素转换为数字: numbers [1, 5, 10, 8] 用一个循环来解决: new_numbers []; for n in numbers:new_n…

APP 后台广告位配置的关键要素与策略

在当今数字化营销的浪潮中,APP 作为重要的信息传播渠道,其后台广告位的配置显得尤为关键。这不仅影响着广告的展示效果,还直接关系到用户体验和平台收益。 首先,了解目标受众是配置广告位的基础。通过对 APP 用户的行为数据进行分…

创建MoveIt! Package

2.1 准备URDF package 首先我们要准备一个机械臂的urdf,如果你已有URDF,可以使用自己的urdf模型。若手头没有现成的URDF,可以从此处下载一个库卡LWR简化模型URDF,这是一个固定底座7自由度的机械臂。 从该连接处依次进入examples/s…

穴位大揭秘:使用「人体穴位图解」,轻松学会精准按摩技巧

软件介绍 人体穴位图解是一款免费无广提供人体穴位图解、人体经络病症及穴位图表的应用,采用目前流行的Flutter框架开发,遍布肺、肠、脾、胃、心、肝等部位。该应用所有资料均来自相关公共医学文献,具有一定的参考价值,通过图文介…

c++算法练习(3)石头剪刀布、输出亲朋字符串、配对碱基对、标准库的字符替换、密码翻译

#include <string>vector<string>results;results.push_bask(string1);for(const auto &result :result)//字符串可以用下表访问string myString;string.length()ss.replace(ss,find(A),1,T);char operator()(char ch) const class SomeClass {private:int mem…

SpringBoot二手车交易管理系统-计算机毕业设计源码02893

目 录 摘要 1 绪论 1.1 选题背景与意义 1.2开发现状 1.3论文结构与章节安排 2 二手车交易管理系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例…