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

4.结构型设计模式 - 第1回:引言与适配器模式 (Adapter Pattern) ——设计模式入门系列

一、引言

在现代软件开发中,设计模式是帮助我们解决复杂问题的工具,它们提供了在常见场景下重用已验证解决方案的途径。而结构型设计模式主要关注类与对象之间的组合方式,旨在通过增强灵活性和降低耦合度来改进代码的结构。

本次讨论的是结构型模式中的第一个:适配器模式 (Adapter Pattern)。它的核心目的是使接口不兼容的类能够协同工作,充当两个类之间的桥梁,保证代码的可扩展性和复用性。

二、适配器模式概述

1. 定义

适配器模式(Adapter Pattern)将一个类的接口转换为客户期望的另一个接口,使得原本接口不兼容的类可以一起工作。它常用于解决“现有接口”与“需要的接口”之间的不兼容问题。

2. 使用场景

适配器模式适用于以下场景:

  • 你希望使用一个现有的类,而它的接口并不符合你的需求。
  • 创建一个可以与多个不相关类协同工作的类,而不修改这些类的接口。

三、适配器模式的结构

适配器模式可以以类适配器和对象适配器两种方式实现:

  1. 类适配器:通过继承的方式实现适配,利用多继承模拟适配。
  2. 对象适配器:通过组合(持有被适配对象的实例)实现适配。
类图:
+--------------------------------+
|           客户端(Client)      |
+--------------------------------+| 使用目标接口v
+--------------------------------+
|           目标接口(Target)   |<-----+
+--------------------------------+      |^                           | 实现目标接口|                           |
+--------------------------------+       |
|           适配器(Adapter)    |-------+ 
| 适配器实现目标接口,并调用被适配对象 |
+--------------------------------+|v
+--------------------------------+
|        被适配者(Adaptee)     |
+--------------------------------+

四、代码实现

以下是一个简单的 Java 示例,展示如何将一个老旧的系统接口适配成新的系统接口。

1. 被适配类 (Adaptee)

// 现有类,无法直接改变
public class LegacyPrinter {public void printText(String text) {System.out.println("Legacy Printer: " + text);}
}

2. 目标接口 (Target)

// 客户端期望的接口
public interface Printer {void print(String message);
}

3. 适配器类 (Adapter)

// 通过适配器将旧的 LegacyPrinter 适配为 Printer 接口
public class PrinterAdapter implements Printer {private LegacyPrinter legacyPrinter;public PrinterAdapter(LegacyPrinter legacyPrinter) {this.legacyPrinter = legacyPrinter;}@Overridepublic void print(String message) {legacyPrinter.printText(message);}
}

4. 客户端代码 (Client)

public class Client {public static void main(String[] args) {Printer printer = new PrinterAdapter(new LegacyPrinter());printer.print("Hello, Adapter Pattern!");}
}

五、类适配器 vs 对象适配器

适配器类型特点优缺点
类适配器通过继承实现,适配器类同时继承了目标接口和被适配者类。优点:简洁,适合单一类适配。缺点:不支持多个类适配,受限于 Java 单继承机制。
对象适配器通过组合实现,适配器类包含一个被适配者类的实例,并实现目标接口。优点:更灵活,支持多个类的适配。缺点:稍微增加了间接层次。

六、案例分析

1. 现实生活案例:电源适配器

一个常见的现实生活中的例子是电源适配器。不同国家的电压标准和插头形状不同,电器设备无法直接使用。但通过电源适配器,电压和插头形状都能被转换为设备所需的标准,从而确保设备正常工作。

2. 综合案例:数据库连接适配器

假设我们有一个旧版数据库系统,它的连接接口已经过时,但现在我们希望在新的系统中使用不同的数据库连接接口。

// 旧版数据库系统
public class OldDatabase {public void connectToDb(String connectionString) {System.out.println("Connecting to database with " + connectionString);}
}// 新系统期望的数据库接口
public interface Database {void connect(String databaseUrl);
}// 适配器,将老接口适配为新接口
public class DatabaseAdapter implements Database {private OldDatabase oldDatabase;public DatabaseAdapter(OldDatabase oldDatabase) {this.oldDatabase = oldDatabase;}@Overridepublic void connect(String databaseUrl) {oldDatabase.connectToDb(databaseUrl);}
}// 客户端代码
public class Client {public static void main(String[] args) {Database db = new DatabaseAdapter(new OldDatabase());db.connect("jdbc:mysql://localhost:3306/mydb");}
}

七、补充与开发建议

在实际开发中,适配器模式是处理代码重构、引入第三方库或与遗留系统集成的有效手段。但在使用适配器时应注意以下几点:

  1. 谨慎过度使用:适配器模式容易滥用,如果系统中出现了大量的适配器类,可能预示着系统设计不够清晰。
  2. 适配的范围:当接口之间差异较大时,使用适配器可能会增加系统复杂性。最好将适配的范围控制在接口定义和调用的边界。
  3. 保持灵活性:为了保持代码的灵活性,可以结合其他模式,如工厂模式,通过工厂创建适配器实例。

八、结论

适配器模式是一种强大的模式,能够在保持原有类功能的同时,使其符合新的需求。通过合理使用,能够增强系统的兼容性和可扩展性。在架构演进和系统重构中,适配器模式是开发人员不可或缺的工具之一。


相关阅读

  • 设计模式入门系列

相关文章:

4.结构型设计模式 - 第1回:引言与适配器模式 (Adapter Pattern) ——设计模式入门系列

一、引言 在现代软件开发中&#xff0c;设计模式是帮助我们解决复杂问题的工具&#xff0c;它们提供了在常见场景下重用已验证解决方案的途径。而结构型设计模式主要关注类与对象之间的组合方式&#xff0c;旨在通过增强灵活性和降低耦合度来改进代码的结构。 本次讨论的是结…...

解决mybatis plus 中 FastjsonTypeHandler无法正确反序列化List类型的问题

由于是根据自动映射类型&#xff0c;我们设置的字段类型是List 也就是反序列化的时候也只是用 FastjsonTypeHandler中的 Override protected Object parse(String json) { return JSON.parseObject(json, type); } 反序列化方法&#xff0c;这是type为List 反序列后我们并没…...

MacOS安装homebrew,jEnv,多版本JDK

1 安装homebrew homebrew官网 根据官网提示&#xff0c;运行安装命令 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装后&#xff0c;bash会提示执行两条命令 (echo; echo eval "$(/opt/homebrew/b…...

【HTTP】认识 URL 和 URL encode

文章目录 认识 URLURL 基本格式**带层次的文件路径****查询字符串****片段标识符** URL encode 认识 URL 计算机中非常重要的概念&#xff0c;并不仅仅是在 HTTP 中使用。用来描述一个网络资源所处的位置&#xff0c;全称“唯一资源定位符” URI 是“唯一资源标识符“严格的说…...

【AI学习笔记】初学机器学习西瓜书概要记录(二)常用的机器学习方法篇

初学机器学习西瓜书的概要记录&#xff08;一&#xff09;机器学习基础知识篇(已完结) 初学机器学习西瓜书的概要记录&#xff08;二&#xff09;常用的机器学习方法篇(持续更新) 初学机器学习西瓜书的概要记录&#xff08;三&#xff09;进阶知识篇(待更) 文字公式撰写不易&am…...

[SDX35+WCN6856]SDX35 + WCN6856 默认增加打包wifi配置hostapd_24g.conf和hostapd_5g.conf操作方法

SDX35 SDX35介绍 SDX35设备是一种多模调制解调器芯片,支持 4G/5G sub-6 技术。它是一个4nm芯片专为实现卓越的性能和能效而设计。它包括一个 1.9 GHz Cortex-A7 应用处理器。 SDX35主要特性 ■ 3GPP Rel. 17 with 5G Reduced Capability (RedCap) support. Backward compati…...

【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数

文章目录 什么是自动引用计数 内存管理/引用计数 概要 内存管理的思考方式 自己生成的对象&#xff0c;自己所持有 非自己生成的对象&#xff0c;自己也能持有 不再需要自己持有的对象时释放 无法释放非自己持有的对象 什么是自动引用计数 自动引用计数&#xff08;AR…...

网络安全-LD_PRELOAD,请求劫持

目录 一、环境 二、开始做题 三、总结原理 四、如何防护 一、环境 我们这里用蚁剑自带的靶场第一关来解释 docker制作一下即可 二、开始做题 首先环境内很明显给我们已经写好了webshell 同样我们也可以访问到 我们使用这个蚁剑把这个webshell连上 我们发现命令不能执行&am…...

GO入门之值传递于引用(指针、内存地址)传递扫盲

GO入门之值传递于引用&#xff08;指针、内存地址&#xff09;传递扫盲 Go 语言中&#xff0c;值传递和引用&#xff08;指针&#xff09;传递是两个关键的概念。通过案例可以很好地展示两者的区别。 值传递与引用传递的区别&#xff1a; 值传递&#xff1a;传递的是变量的副…...

【渗透测试】-vulnhub源码框架漏洞-Os-hackNos-1

vulnhub源码框架漏洞中的CVE-2018-7600-Drupal 7.57 文章目录  前言 1.靶场搭建&#xff1a; 2.信息搜集&#xff1a; 主机探测&#xff1a; 端口扫描&#xff1a; 目录扫描&#xff1a; 3.分析&#xff1a; 4.步骤&#xff1a; 1.下载CVE-2018-7600的exp 2.执行exp: 3.写入木…...

sqli-lab靶场学习(三)——Less8-10(盲注、时间盲注)

Less8 第八关依然是先看一般状态 http://localhost/sqli-labs/Less-8/?id1 然后用单引号闭合&#xff1a; http://localhost/sqli-labs/Less-8/?id1 这关的问题在于报错是不显示&#xff0c;那没办法通过上篇文章的updatexml大法处理。对于这种情况&#xff0c;需要用“盲…...

Pybullet 安装过程

Pybullet 安装过程&#xff08;windows&#xff09; 1. 安装C编译工具2. 安装Pybullet 1. 安装C编译工具 pybullet 需要C编译套件&#xff0c;直接装之前检查下&#xff0c;要不会报缺少某版本MVSC的error&#xff0c;最好的方式是直接下载visual studio&#xff0c;直接按默认…...

Error when custom data is added to Azure OpenAI Service Deployment

题意&#xff1a;在向 Azure OpenAI 服务部署添加自定义数据时出现错误。 问题背景&#xff1a; I receive the following error when adding my custom data which is a .txt file (it doesnt matter whether I add it via Azure Cognitive Search, Azure Blob Storage, or F…...

libreoffice word转pdf

一、准备一个word文件 运行&#xff1a; cd /root libreoffice --headless --convert-to pdf --outdir /root/output doc1.docx 发现中文乱码&#xff1a; 此时我们需要给linux 上添加中文字体&#xff1a; centos7 添加中文字体 再次运行正常&#xff1a; libreoffice --h…...

java -----泛型

泛型的理解和好处 泛型是在JDK5之后引入的一个新特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查。 泛型的格式为 <数据类型> import java.util.ArrayList;SuppressWarnings({"all"}) public class Generic02 {public static void…...

Springboot 文件上传下载相关问题

文章目录 关于Springboot 文件上传下载问题解决方案注意事项文件上传文件下载文件删除文件在线打开在写练习的时候&#xff0c;发现了一些小小的问题&#xff0c;已经在 上述代码中体现。① 代码路径碰到中文的时候&#xff0c;会有乱码&#xff0c;需要转换&#xff08;内容中…...

【Kotlin 与 Java 互操作】Java中调用带有默认值的Kotlin函数(十四)

导读大纲 1.0.1 Java 没有默认参数值的概念1.0.2 使用 JvmOverloads 来简化调用 1.0.1 Java 没有默认参数值的概念 因此当从 Java 调用带有默认参数值的 Kotlin 函数时 1. 必须明确指定所有参数值 fun <T> joinToString(collection: Collection<T>,separator: St…...

点赞系统实现

点赞功能是社交、电商等几乎所有的互联网项目中都广泛使用。虽然看起来简单&#xff0c;不过蕴含的技术方案和手段还是比较多的。 下面将分享之前做的判题OJ系统的点赞系统的思路。 1.需求分析 点赞功能与其它功能不同&#xff0c;没有复杂的原型和需求&#xff0c;仅仅是一…...

c++进阶学习-----继承

1.继承的概念及定义 1.1继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。 继承呈现了面向对象 程序设计的…...

C++学习笔记(37)

302、makefile 在实际开发中&#xff0c;项目的源代码文件比较多&#xff0c;按类型、功能、模块分别存放在不同的目录和文件中&#xff0c;哪 些文件需要先编译&#xff0c;那些文件后编译&#xff0c;那些文件需要重新编译&#xff0c;还有更多更复杂的操作。 make 是一个强大…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...