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

设计模式:适配器模式

定义

适配器模式(Adapter Pattern),也称为包装器(Wrapper)模式,是一种结构型设计模式,它允许不兼容的接口之间进行交互。适配器模式通过包装一个已有的类,提供一个与原系统兼容的接口,从而使得原本由于接口不兼容而不能一起工作的类可以协同工作。

应用场景

适配器模式通常在以下场景中使用:

  • 当你希望使用某个类,但是它的接口与其他代码不兼容时。
  • 当你想创建一个可重用的类,该类可以与未知的或未来的类(即那些接口可能不兼容的类)协同工作。
  • 当你需要使用几个现有的子类,但是子类化每个类以适配它们的接口会导致代码可用性下降时。

示例

假设有一个旧的电子邮件系统,它的客户端代码只能与EmailClient接口兼容。现在,你想要集成一个新的邮件系统,但是其接口与旧系统不兼容。适配器模式可以在这里发挥作用。

// 旧的电子邮件客户端接口
public interface EmailClient {void sendEmail(String messageBody);
}// 新的邮件系统接口
public interface AdvancedEmailClient {void sendEmailMessage(String subject, String body);
}// 适配器实现
public class EmailAdapter implements EmailClient {private AdvancedEmailClient advancedEmailClient;public EmailAdapter(AdvancedEmailClient client) {this.advancedEmailClient = client;}@Overridepublic void sendEmail(String messageBody) {advancedEmailClient.sendEmailMessage("Adapted", messageBody);}
}// 新邮件系统类实现
public class NewEmailSystem implements AdvancedEmailClient {public void sendEmailMessage(String subject, String body) {// 新邮件系统的发送逻辑}
}// 客户端代码
public class Client {public static void main(String[] args) {AdvancedEmailClient newEmailSystem = new NewEmailSystem();EmailClient client = new EmailAdapter(newEmailSystem);client.sendEmail("Hello World!");}
}

原则间的权衡与冲突

适配器模式遵循了以下设计原则:

  • 开闭原则:允许系统接受新的适配器或已有适配器的变化,而无需修改现有代码。
  • 单一职责原则:适配器类的唯一职责是将一个接口转换为另一个接口。

然而,过多地使用适配器可能会导致系统中类的数量增加,并且增加系统的复杂性,这可能与简洁性(KISS)原则和最少知识原则(Law of Demeter)相冲突。

设计模式的局限性

  • 过度使用:过度使用适配器可能会导致系统变得非常混乱,很难理解和维护。
  • 不是万能的:适配器模式无法适配所有的接口问题,特别是当待适配的类的接口非常复杂时。

总结与建议

适配器模式是实现系统间组件接口兼容的一个有效途径。它允许现有系统与第三方库、新系统或者未来的系统进行交互,而不需要修改现有的代码。

建议在以下情况使用适配器模式:

  • 需要使用现有类,但其接口与其他代码不兼容时。
  • 需要创建可以与未知或不相关的类协同工作的灵活代码时。

在设计系统时,应当谨慎使用适配器模式,以避免不必要的复杂性。如果接口不匹配的问题可以通过重构来解决,那么可能更应该选择重构而非适配器。适配器模式应当作为连接不兼容接口的最后手段,而不是首选解决方案。

相关文章:

  • Linux 内核的构建块:深入探索 C 结构体的应用
  • 蓝桥杯-冶炼金属(二分求最大最小)
  • 搭建前后端的链接(java)
  • 5.4Python之可变类型与列表的深浅拷贝
  • React 状态管理:安全高效地修改对象属性的 3 种方法
  • Linux CPU利用率
  • 通往 AGI 的道路上,OpenAI 逐渐构建了全模态的工具集
  • 【算法优选】 动态规划之简单多状态dp问题——贰
  • OpenHarmony分布式软总线API调用测试工具 softbus_tool使用说明
  • 设计模式-接口隔离原则
  • CountDownLatch 详解
  • Java基础知识总结(48)
  • 106. 跑步锻炼(结果填空)
  • 蓝桥杯 2022 省 B 洛谷 P8787 砍竹子
  • Terminal常见快捷命令(持续更新)
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • centos安装java运行环境jdk+tomcat
  • dva中组件的懒加载
  • Fastjson的基本使用方法大全
  • fetch 从初识到应用
  • JavaScript-Array类型
  • Java-详解HashMap
  • php ci框架整合银盛支付
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • 基于web的全景—— Pannellum小试
  • 技术胖1-4季视频复习— (看视频笔记)
  • 理清楚Vue的结构
  • 如何用vue打造一个移动端音乐播放器
  • 入手阿里云新服务器的部署NODE
  • 数据结构java版之冒泡排序及优化
  • 听说你叫Java(二)–Servlet请求
  • 微信开放平台全网发布【失败】的几点排查方法
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • (C++20) consteval立即函数
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)memcache、redis缓存
  • (转载)(官方)UE4--图像编程----着色器开发
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • *Django中的Ajax 纯js的书写样式1
  • . Flume面试题
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET开发不可不知、不可不用的辅助类(一)
  • .net网站发布-允许更新此预编译站点
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @Valid和@NotNull字段校验使用
  • [ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现
  • [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序...