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

Java设计模式之适配器模式

目录

1、介绍

1.1、适配器模式的基本结构

1.2、原理

2、实现方式

2.1、对象适配器模式

2.2、类适配器模式

2.3、接口适配器模式

3、在 Java 框架中的应用

3.1、springmvc适配器模式

3.2、JDBC驱动软件

3.3、Java I/O中的适配器模式      

4、适配器模式的优缺点

4.1、优点

4.2、缺点


前言

        适配器模式(Adapter Pattern)是一种 结构型设计模式,用于在两个不兼容的接口之间建立桥梁,使它们可以协同工作

        它通常用于让已有的类与新接口兼容,而无需修改原有代码

相比较于其他模式:

        典型应用包括 Spring MVC HandlerAdapterJava I/O InputStreamReaderAOP AdvisorAdapter 等,是一种非常常见的设计模式。


1、介绍

java的设计模式可分为:创建型模式、结构性模式行为型模式三类。

如下图所示:

1.1、适配器模式的基本结构


1、目标接口(Target):

定义客户期望的接口。


2、被适配者(Adaptee):

需要适配的类,通常已有不兼容的方法。


3、适配器(Adapter):

连接 Target 和 Adaptee,使其兼容。

1.2、原理

可参考如下所示:


2、实现方式

适配器模式有三种主要形式:

1、对象适配器(基于组合)


2、类适配器(基于继承)


3、接口适配器(基于抽象类)

如下图所示:

java的6大原则开闭原则,可参考:

Java语言的设计原则-CSDN博客https://blog.csdn.net/weixin_50055999/article/details/148061298?spm=1011.2415.3001.5331

通俗讲:对于目标接口,扩展功能是开放的、修改已有功能是关闭的。

2.1、对象适配器模式

        对象适配器使用 组合 方式,让适配器持有 Adaptee(被适配者) 实例,在 Adapter(适配器) 中调用 Adaptee 的方法。

示例:将 220V 电压适配为 5V

// 目标接口:手机充电器希望得到 5V 电压
interface Voltage5V {int output5V();
}// 被适配者:现有 220V 电压
class Voltage220V {public int output220V() {return 220;}
}// 适配器:适配 220V 到 5V
class VoltageAdapter implements Voltage5V {private Voltage220V voltage220V; // 组合方式public VoltageAdapter(Voltage220V voltage220V) {this.voltage220V = voltage220V;}@Overridepublic int output5V() {int src = voltage220V.output220V();return src / 44; // 转换为 5V}
}// 客户端代码
public class AdapterPatternDemo {public static void main(String[] args) {Voltage220V voltage220V = new Voltage220V();VoltageAdapter adapter = new VoltageAdapter(voltage220V);System.out.println("输出电压:" + adapter.output5V() + "V");}
}

优点

  • 遵循 组合优先于继承,不改变 Adaptee 的代码。
  • 可以适配多个 Adaptee,更灵活。

2.2、类适配器模式

类适配器使用 继承 方式,使 Adapter 继承 Adaptee 并实现 Target 接口。


// 目标接口:手机充电器希望得到 5V 电压
interface Voltage5V {int output5V();
}// 被适配者:现有 220V 电压
class Voltage220V {public int output220V() {return 220;}
}// 适配器:继承 Voltage220V,实现 Voltage5V
class VoltageClassAdapter extends Voltage220V implements Voltage5V {@Overridepublic int output5V() {int src = output220V(); // 直接调用父类方法return src / 44;}
}

缺点

  • 由于 Java 不支持多继承,适配器无法同时适配多个 Adaptee
  • 适配器与 Adaptee 绑定,不够灵活。

2.3、接口适配器模式

基于抽类类、适用于接口中有多个方法,但客户端只需实现其中一部分的情况。

// 原始接口
interface MouseListener {void onClick();void onDoubleClick();void onRightClick();
}// 适配器:提供默认实现,子类只需实现需要的方法
abstract class MouseAdapter implements MouseListener {@Override public void onClick() {}@Override public void onDoubleClick() {}@Override public void onRightClick() {}
}// 只关心单击事件的子类
class ClickListener extends MouseAdapter {@Overridepublic void onClick() {System.out.println("单击事件触发");}
}

优点

  • 让子类只需覆盖需要的方法,避免实现所有方法。
  • 常用于 Java SwingServlet API 的监听器适配。

3、在 Java 框架中的应用

3.1、springmvc适配器模式

具体流程如下:

可参考:谈谈对SpringMvc的理解-CSDN博客https://blog.csdn.net/weixin_50055999/article/details/147568550?spm=1011.2415.3001.5331

Spring 定义了一个适配接口,使得每一种 Controller 有一种对应的适配器实现类。

3.2、JDBC驱动软件


        数据库连接工具JDBC使得Java语言程序能够连接到数据库上,并适用SQL来查询和修改数据和数据定义。

        每个数据库引擎的JDBC驱动软件都是一个介于JDBC接口和数据库引擎之间的适配器软件。

        抽象的JDBC接口和各个数据库引擎的API之间都需要相应的适配器软件,即为各个数据库引擎准备的驱动软件

3.3、Java I/O中的适配器模式      

        InputStreamReader和OutputStreamWriter类分别继承了Reader和Writer抽象类。但是,要创建他们的对象需要在构造器中传入一个InputStream和OutputStream的实例。

        InputStreamReader和OutputStreamWriter的作用也就是将InputStream和OutputStream适配到Reader和Writer。

InputStreamReader的类结构图:

        InputStreamReader实现了Reader接口,并且持有了InputStream的引用,这里是通过StreamDecoder类间接持有的,因为从byte到char要经过编码。

        很显然适配器就是InputStreamReader类,而源角色就是InputStream代表的实例对象。目标接口就是Reader类。OutputStreamWriter类也是类似的方式。


4、适配器模式的优缺点


4.1、优点


解耦:让原本不兼容的类可以协同工作,而不修改原有代码。


复用:可以复用 Adaptee,减少重复代码。


扩展性强:对象适配器模式可以适配多个 Adaptee,不受继承限制。


4.2、缺点


可能增加系统复杂度:引入额外的适配器层,增加类的数量。


类适配器受限:由于 Java 不支持多继承,类适配器不能适配多个 Adaptee。


总结

对象适配器(推荐):使用 组合 方式,灵活性高,适用于大多数情况。


类适配器(局限性):使用 继承,不能适配多个 Adaptee。


接口适配器(缺省适配):适用于接口方法多,但只需要部分实现的情况。


参考文章:

1、Java 中的适配器模式(Adapter Pattern)_java 适配器模式-CSDN博客https://blog.csdn.net/weixin_50992793/article/details/145979464?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522061adfa13cad0afadbf8526fac6e5aad%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=061adfa13cad0afadbf8526fac6e5aad&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-145979464-null-null.142^v102^pc_search_result_base1&utm_term=java%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F&spm=1018.2226.3001.4187

2、java适配器模式(Adapter)-结构型_adapter-jdbc-CSDN博客https://blog.csdn.net/sunxianghuang/article/details/51816784?ops_request_misc=&request_id=&biz_id=102&utm_term=java%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-5-51816784.142^v102^pc_search_result_base1&spm=1018.2226.3001.4187

http://www.lqws.cn/news/478639.html

相关文章:

  • Linux 内核配置核心文件config与流程
  • MATLAB的readmatrix函数
  • Electron架构深度解析:用Web技术构建桌面应用的桥梁
  • 什么是缺口箱线图?如何绘制?
  • .Net 9.0环境下WebApi发布到IIS
  • VB.NET,C#在线程中修改UI的安全操作
  • rknn优化教程(三)
  • WEB3开启 Hardhat 自动验证有什么意义
  • uview ui request get / post 传参含params和json数据的分析和使用
  • 【Redis】解码Redis中hash类型:理解基础命令,以及内部编码方式和使用场景
  • 原创模板--微信小程序 实现的背单词程序
  • 62-Oracle ADR(Automatic Diagnostic Repository)
  • 二、Generative adversarial network (GAN)
  • Spring Boot Actuator 跟踪HTTP请求和响应
  • 【数据结构与算法】数据结构初阶:详解顺序表和链表(一)
  • C++,Qt事件处理机制编程开发练习全解析,23000字解析!!
  • RabbitMQ从入门到实践:消息队列核心原理与典型应用场景
  • Oracle 数据库查询:单表查询
  • 嵌入式通信协议框架的四层架构设计与实现
  • 【云原生】Docker 部署 Elasticsearch 9 操作详解
  • 华为OD-2024年E卷-字符串化繁为简[200分] -- python
  • 「Linux文件及目录管理」vi、vim编辑器
  • Ragflow 源码:task_executor.py
  • Sqlserver 设置对特定数据库特定表只读访问权限
  • 1928: 日期差值 codeup
  • MySQL安装与配置【windowsMac】
  • Unity3D仿星露谷物语开发69之动作声音
  • Unity Addressable使用之服务器远程加载
  • leetcode:面试题 08.01. 三步问题
  • AWS认证系列:考点解析 - cloud trail,cloud watch,aws config