程序员必知!适配器模式的实战应用与案例分析

程序员必知!适配器模式的实战应用与案例分析 - 程序员古德

适配器模式是一种结构型设计模式,它允许不同接口的对象协同工作,它通过将一个类的接口转换成客户希望的另外一个接口,使得不兼容的类可以一起工作。适配器模式提高了类的复用性、系统的灵活性和可扩展性,并降低了系统间的耦合度,在实际应用中,例如电源适配器和数据转换器,以及编程中封装老旧接口或第三方库都体现了适配器模式的应用。

定义

程序员必知!适配器模式的实战应用与案例分析 - 程序员古德

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许对象具有不同的接口协同工作,这种类型的设计模式属于结构模式,因为此模式作用于对象的结构。

在适配器模式中,我们通过将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。它的主要作用是解决两个已有接口间不兼容的问题,它允许我们在不修改现有代码的情况下,将两个不兼容的接口通过适配器进行对接,从而使得它们能够协同工作,它在实际应用中的例子有很多,比如电源适配器、数据转换器等。在编程中,适配器模式也经常用于封装老旧的接口或者第三方库,以便它们能够与新的代码或框架协同工作,适配器模式的主要优点有:

  1. 提高了类的复用性,通过适配器模式,我们可以将已有的类进行复用,而无需修改其结构。
  2. 提高了系统的灵活性和可扩展性,当需要引入一个新的接口时,只需增加一个新的适配器类,而无需修改原有代码。
  3. 降低了系统间的耦合度,通过适配器模式,我们可以将原本紧密耦合的两个系统解耦,从而提高系统的可维护性和稳定性。

代码案例

程序员必知!适配器模式的实战应用与案例分析 - 程序员古德

使用演示

下面演示了未使用适配器模式的代码和使用了适配器模式的代码,如下代码:

1、未使用适配器模式的反例,假设我们有一个已有的类 OldClass,这个类的方法不满足客户端的需求:

// 已有的类,不满足客户端需求  
public class OldClass {  public void specificRequest() {  System.out.println("OldClass specific request.");  }  
}  // 客户端代码  
public class Client {  public static void main(String[] args) {  OldClass oldClass = new OldClass();  // 客户端需要调用 request() 方法,但是 OldClass 没有此方法  // oldClass.request(); // 这行代码会导致编译错误  oldClass.specificRequest(); // 只能调用已有的方法  }  
}

在上述反例中,Client 希望调用一个名为 request() 的方法,但是 OldClass 只有 specificRequest() 方法,这导致 Client 无法直接使用 OldClass

2、使用适配器模式的正例,为了解决上述问题,我们可以使用适配器模式,将一个类的接口转换成客户端所期望的另一种接口,从而使得原本由于接口不兼容而无法在一起工作的类能够一起工作,如下代码:

// 目标接口,定义客户端需要的方法  
public interface Target {  void request();  
}  // 适配器类,继承 OldClass 并实现 Target 接口  
public class Adapter extends OldClass implements Target {  @Override  public void request() {  // 调用 OldClass 的 specificRequest() 方法,并可能进行其他操作以满足客户端需求  super.specificRequest();  System.out.println("Adapter additional operation.");  }  
}  // 客户端代码  
public class Client {  public static void main(String[] args) {  // 使用适配器类,而不是直接使用 OldClass  Target target = new Adapter();  target.request(); // 现在可以调用 request() 方法了  }  
}

运行上述客户端代码后,输出将会是:

OldClass specific request.  
Adapter additional operation.

通过适配器模式,我们成功地让 Client 能够使用 OldClass 的功能,同时满足了自己对接口的需求。在适配器中,我们可以添加额外的操作或转换来满足客户端的需求。

场景演示

场景一:电源适配器

假设我们有一个Voltage220类提供220V电压,但我们需要一个110V的电压接口,此时,我们可以使用适配器模式将220V电压适配为110V电压,如下代码:

// 目标接口  
public interface Voltage110 {  int output110Voltage();  
}  // 已有的类,提供220V电压  
public class Voltage220 {  public int output220Voltage() {  return 220;  }  
}  // 电源适配器类  
public class PowerAdapter implements Voltage110 {  private Voltage220 voltage220;  public PowerAdapter(Voltage220 voltage220) {  this.voltage220 = voltage220;  }  @Override  public int output110Voltage() {  int srcVoltage = voltage220.output220Voltage();  int dstVoltage = srcVoltage / 2; // 适配为110V电压  return dstVoltage;  }  
}  // 客户端调用  
public class Client {  public static void main(String[] args) {  Voltage220 voltage220 = new Voltage220();  PowerAdapter powerAdapter = new PowerAdapter(voltage220);  int adaptedVoltage = powerAdapter.output110Voltage();  System.out.println("Adapted voltage: " + adaptedVoltage + "V"); // 输出:Adapted voltage: 110V  }  
}

场景二:数据格式转换

假设我们有一个老的数据读取接口OldDataReader,它返回的数据格式是XML,但现在我们需要一个返回JSON格式数据的新接口,我们可以使用适配器模式来完成这个转换,如下代码:

// 目标接口,返回JSON格式数据  
public interface NewDataReader {  String readDataAsJson();  
}  // 已有的类,返回XML格式数据  
public class OldDataReader {  public String readDataAsXml() {  return "<data><item>Item1</item><item>Item2</item></data>"; // 示例XML数据  }  
}  // 数据格式适配器类  
import org.json.XML; // 假设我们使用org.json库进行XML到JSON的转换  public class DataFormatAdapter implements NewDataReader {  private OldDataReader oldDataReader;  public DataFormatAdapter(OldDataReader oldDataReader) {  this.oldDataReader = oldDataReader;  }  @Override  public String readDataAsJson() {  String xmlData = oldDataReader.readDataAsXml();  String jsonData = XML.toJSONObject(xmlData).toString(); // 将XML转换为JSON  return jsonData;  }  
}  // 客户端调用  
public class Client {  public static void main(String[] args) {  OldDataReader oldDataReader = new OldDataReader();  DataFormatAdapter dataFormatAdapter = new DataFormatAdapter(oldDataReader);  String jsonData = dataFormatAdapter.readDataAsJson();  System.out.println("Adapted JSON data: " + jsonData); // 输出转换后的JSON数据  }  
}

核心总结

程序员必知!抽象工厂模式的实战应用与案例分析 - 程序员古德

适配器模式的优点主要表现在兼容性、透明性、灵活性和解耦四个方面。它能够将已存在的类整合到新的环境中,无需修改原有代码,从而提高了软件的可复用性,客户端通过适配器与目标对象交互,仍能使用一套统一的接口,对客户端透明,简化了客户端的使用。适配器模式将接口与实现分离,降低了系统各部分之间的耦合度,使得系统更加模块化,易于维护。

在实际应用中,适配器模式在处理老旧系统与新系统整合、第三方库的使用以及不同团队或部门间接口不统一等问题上效果显著,它使得原本由于接口不兼容而无法协同工作的类能够合作无间,提高了系统的整体效率和可维护性。比如,在引入新的第三方库时,如果其接口与现有系统不兼容,我们可以通过适配器模式将两者整合在一起,而无需对现有系统进行大规模修改。

适配器模式也存在一些缺点,比如:增加额外类和代码可能导致系统复杂性上升,由于中间层的存在,可能带来一定的性能开销,过多使用适配器会使代码结构变得复杂,影响可读性。

要适度使用适配器模式,只在必要时使用,避免过度复杂化系统,要明确适配器的目标接口,确保其与客户端需求一致。在性能敏感的场景下,需谨慎评估适配器模式带来的性能开销,可以考虑结合其他设计模式如桥接模式、装饰器模式等使用,以应对更复杂的场景。比如,在需要动态添加或删除功能时,可以结合装饰器模式使用;在需要处理多个平台或设备的兼容性问题时,可以结合桥接模式使用。

关注我,每天学习互联网编程技术 - 程序员古德

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

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

相关文章

React快速入门之组件

目录 组件JSX在标签使用{}嵌入JS表达式使用组件组件嵌套以&#x1f332;树的方式管理组件间的关系组件纯粹原则 组件 文件&#xff1a;Profile.js export default function Profile({isPacked true&#xff0c;head,stlyeTmp,src,size 80}) {if (isPacked) {head head &q…

在SpringBoot中自定义指标并使用Prometheus监控报警

公众号「架构成长指南」&#xff0c;专注于生产实践、云原生、分布式系统、大数据技术分享 在10 分钟教你使用Prometheus监控Spring Boot工程中介绍了如何使用Prometheus监控Spring Boot提供的默认指标&#xff0c;这篇介绍如何自定义业务指标&#xff0c;并使用Prometheus进行…

秋招复习篇之代码规范

目录 前言 1、变量命名 2、代码空格 1&#xff09;操作符左右一定有空格&#xff0c; 2&#xff09;分隔符&#xff08;, 和;&#xff09;前一位没有空格&#xff0c;后一位保持空格&#xff0c;例如&#xff1a; 3&#xff09;大括号和函数保持同一行&#xff0c;并有一个空格…

JavaScript Class类 | 类的继承 - 类的使用 -原型与原型链

文章目录 JavaScript class类基础概念属性与方法相关概念私有字段类的name属性 返回类的名字类的访问器方法super关键字 new的过程中发生了什么extends继承 重写-重载 语法细节类声明与类表达式补充理解:let和const的作用域提升规则 类的继承原型与隐式原型链特殊原型链 原型链…

【C++核心编程(一)】

一、内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域&#xff1a; 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的。 全局区&#xff1a;存放全局变量和静态变量以及常量。 栈区&#xff1a;由编译器自动分配释放,存放函数的…

第52周,第三期技术动态

大家好&#xff0c;才是真的好。 今天周五&#xff0c;我们主要介绍与Domino相关产品新闻&#xff0c;以及互联网或其他IT行业动态等。 一、HCL Domino将重新开发和发布应用市场 为了持续吸引新客户&#xff0c;现有客户以及技术爱好者和专业人士&#xff0c;在2023年的 Col…

6种大模型的使用方式总结,使用领域数据集持续做无监督预训练可能是一个好选择

本文原文来自DataLearnerAI官方网站&#xff1a;6种大模型的使用方式总结&#xff0c;使用领域数据集持续做无监督预训练可能是一个好选择 | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051703426665726 Sebastian Raschka是LightningAI的首席科学家&…

数字身份验证:跨境电商如何应对账户安全挑战?

在数字化时代&#xff0c;随着跨境电商的蓬勃发展&#xff0c;账户安全问题逐渐成为行业和消费者关注的焦点。随着网络犯罪日益猖獗&#xff0c;用户的数字身份安全面临着更加复杂的威胁。本文将深入探讨数字身份验证在跨境电商中的重要性&#xff0c;并探讨各种创新技术和策略…

前端使用高德api的AMap.Autocomplete无效,使用AMap.Autocomplete报错

今天需要一个坐标拾取器&#xff0c;需要一个输入框输入模糊地址能筛选的功能 查看官方文档&#xff0c;有一个api可以直接满足我们的需求 AMap.Autocomplete 上代码 AMapLoader.load({"key": "你的key", // 申请好的Web端开发者Key&#xff0c;首次调…

XHR与Fetch的功能异同点列表

XHR与Fetch的功能异同点列表

2012年第一届数学建模国际赛小美赛B题大规模灭绝尚未到来解题全过程文档及程序

2012年第一届数学建模国际赛小美赛 B题 大规模灭绝尚未到来 原题再现&#xff1a; 亚马逊是地球上现存最大的雨林&#xff0c;比地球上任何地方都有更多的野生动物。它位于南美洲大陆的北侧&#xff0c;共有9个国家&#xff1a;巴西、玻利维亚、厄瓜多尔、秘鲁、哥伦比亚、委…

哪种猫粮比较好?超能打的5款主食冻干测评

不知道从什么时候开始掀起一股冻干喂养风&#xff0c;各种查资料阅读文献发现冻干喂养是最适合忙碌地打工人的“生骨肉喂养”替代版&#xff0c;是最符合猫咪饮食天性的一种。很多养猫人纷纷开始冻干喂养&#xff0c;但对于主食冻干猫粮的选择就让很多猫奴犯了难在电商平台随便…