设计模式(六)-----适配器模式(Adapter Pattern)

目录

  • 什么是适配器模式
  • 适用场景
  • 适配器模式的三种实现方式
    • 1. 类的适配器模式
    • 2. 对象的适配器模式
    • 3. 接口的适配器模式
  • 总结

什么是适配器模式

适配器模式主要用于将一个类的接口转化成客户端希望的目标类格式,使得原本不兼容的类可以在一起工作,将目标类和适配者类解耦;同时也符合“开闭原则”,可以在不修改原代码的基础上增加新的适配器类;将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性,但是缺点在于更换适配器的实现过程比较复杂。

适用场景

  • 将旧的接口适配成新的接口
    在软件开发中,我们经常会遇到需要使用旧的类或组件,但它们的接口与我们期望的接口不兼容的情况。这时候,我们可以使用适配器模式将旧的接口适配成新的接口,使其能够协同工作。例如,Java中的InputStreamReader类就是一个适配器模式的应用,它将字节流转换成字符流,以便于读取文本文件。

  • 将多个类的接口适配成统一的接口
    在某些情况下,我们可能需要将多个类的接口适配成统一的接口,以便于我们能够使用它们的共同特性。例如,Java中的Enumeration接口定义了一组方法,可以遍历集合中的元素。但是,在Java 1.0中,集合类没有实现这个接口,而是使用了一个名为"elements"的方法。为了使集合类能够遵循Enumeration接口,Java提供了一个适配器类叫做"Iterator",它将"elements"方法适配成Enumeration接口的方法。

  • 在不改变原有代码的情况下,增加新的功能
    适配器模式还可以用于在不改变原有代码的情况下,增加新的功能。例如,如果我们想要给一个已经存在的类增加一些额外的功能,但是又不想修改这个类的代码,那么我们可以使用适配器模式来实现这个目的。具体的做法是,创建一个适配器类,将原有类的对象作为适配器类的成员变量,并在适配器类中添加新的方法。

适配器模式的三种实现方式

1. 类的适配器模式

  • 目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
  • 需要适配的类(Adaptee):需要适配的类或适配者类。
  • 适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。

完整代码

已存在的,但是拥有不符合我们要求接口的类

public class Adaptee {public void specificRequest() {System.out.println("被适配类具有 特殊功能...");}
}

目标接口,就是我们需要的统一接口

public interface Target {void request();
}

具体目标类,只提供普通功能,就是实现统一接口的普通类

public class ConcreteTarget implements Target{@Overridepublic void request() {System.out.println("我是普通类,实现普通功能");}
}

适配器类,继承了被适配类,同时实现标准接口

public class Adapter extends Adaptee implements Target{@Overridepublic void request() {super.specificRequest();}
}

测试

public class Client {public static void main(String[] args) {// 使用普通功能类Target concreteTarget = new ConcreteTarget();concreteTarget.request();// 使用特殊功能类,即适配类Target adapter = new Adapter();adapter.request();}
}

结果
在这里插入图片描述

2. 对象的适配器模式

class Adapter implements Target{// 直接关联被适配类private Adaptee adaptee;// 可以通过构造函数传入具体需要适配的被适配类对象public Adapter (Adaptee adaptee) {this.adaptee = adaptee;}public void request() {// 这里是使用委托的方式完成特殊功能this.adaptee.specificRequest();}
}// 测试类
public class Client {public static void main(String[] args) {// 使用普通功能类Target concreteTarget = new ConcreteTarget();concreteTarget.request();// 使用特殊功能类,即适配类,// 需要先创建一个被适配类的对象作为参数Target adapter = new Adapter(new Adaptee());adapter.request();}
}

测试结果与上面的一致。从类图中我们也知道需要修改的只不过就是 Adapter 类的内部结构,即 Adapter 自身必须先拥有一个被适配类的对象,再把具体的特殊功能委托给这个对象来实现。使用对象适配器模式,可以使得 Adapter 类(适配类)根据传入的 Adaptee 对象达到适配多个不同被适配类的功能,当然,此时我们可以为多个被适配类提取出一个接口或抽象类。这样看起来的话,似乎对象适配器模式更加灵活一点。

3. 接口的适配器模式

有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行

public interface Sourceable {void method1();void method2();void method3();void method4();
}
public abstract class Wrapper implements Sourceable{@Overridepublic void method1() {}@Overridepublic void method2() {}@Overridepublic void method3() {}@Overridepublic void method4() {}
}
public class WrapperSub extends Wrapper{@Overridepublic void method1() {System.out.println("是我method1");}
}
public class WrapperSub1 extends Wrapper{@Overridepublic void method2() {System.out.println("我是method2");}
}
public class Client {public static void main(String[] args) {WrapperSub wrapperSub = new WrapperSub();wrapperSub.method1();WrapperSub1 wrapperSub1 = new WrapperSub1();wrapperSub1.method2();}
}

在这里插入图片描述

总结

适配器模式是一种非常常见的设计模式,它可以帮助我们解决不兼容的类或接口之间的问题,同时也可以帮助我们在不改变原有代码的情况下,增加新的功能。

参考:

https://blog.csdn.net/2302_77835532/article/details/130664014
https://blog.csdn.net/a745233700/article/details/83628122

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

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

相关文章

【智能时代的颠覆】AI让物联网不再是物联网

自我介绍⛵ 📣我是秋说,研究人工智能、大数据等前沿技术,传递Java、Python等语言知识。 🙉主页链接:秋说的博客 📆 学习专栏推荐:MySQL进阶之路、C刷题集、网络安全攻防姿势总结 欢迎点赞 &…

WIFI鉴权的过程

1.前言 当今手机连接WIFI热点普遍采用WPA2-PSK的方式。本文讨论这个方式的鉴权过程。 2. 鉴权过程 我们称需要连接的一方为station,简称STA。提供WIFI热点的一方为AP。 连接之前, station需要知道AP的名字(ssid)和密码(PSK)。 定义 &#x…

GD32F303 DAM串口接收

1.设置串口 串口配置比较常规,我只应用的空闲中断。 2.DMA设置 我设置的DMA是串口接收到数据后保存到数组里,数组满了以后会自动从头开始,并且会进入一次DMA中断。

http连接处理(中)(四)

2. 结合代码分析请求报文解析 上一节我们对http连接的基础知识、服务器接收请求的处理流程进行了介绍,接下来将结合流程图和代码分别对状态机和服务器解析请求报文进行详解。 流程图部分,描述主、从状态机调用关系与状态转移过程。 代码部分&#xff…

度规对列排斥能的影响

( A, B )---1*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有1个节点,A,B训练集各只有1张图片,让A是0,B是1,统计迭代次数。 在收敛误差为7e-4的时候收敛199次, 差值结构 A-B 迭代次数 1 1-0 27191.925…

面试题更新之-CSS Hack是什么?ie6,7,8的hack分别是什么?

文章目录 导文CSS Hack的定义广泛应用的CSS Hack技巧ie6,7,8的hack分别是什么? 导文 面试题更新之-CSS Hack是什么?ie6,7,8的hack分别是什么? CSS Hack的定义 CSS Hack指的是在CSS中使用一些特定的代码或技巧,通过利用不同浏览器对CSS实现的…

黑马大数据学习笔记2-HDFS环境部署

目录 环境部署hadoop-3.3.4.tar.gz构建软链接配置workers文件夹配置hadoop-env.sh文件配置core-site.xml文件配置hdfs-site.xml文件准备数据目录分发Hadoop文件夹将Hadoop的一些脚本、程序配置到PATH中授权为hadoop用户格式化整个文件系统查看HDFS WEBUI保存快照 https://www.b…

[MySQL]MySQL内外连接

[MySQL]MySQL内外连接 文章目录 [MySQL]MySQL内外连接1. 内连接2. 外连接2.1 左外连接2.2 右外连接 3. 简单练习 1. 内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,也是在开发过程中使用的最多的连接查询。 语法: SELECT ... FR…

001- database - 数据库

1、新的数据库进入默认有四个数据库,一般不要轻易删除; -- 创建数据库 CREATE DATABASE 数据库名 -- 查询所有数据库 SHOW DATABASES -- 使用数据库 -- USE 数据库名 -- 查询当前使用的数据库 SELECT DATABASE() -- 删除数据库 DROP DATABASE 数据库名

Apache Tomcat 信息泄露漏洞CVE-2023-28708处理

一、漏洞描述 Apache Tomcat软件是Jakarta Servlet、 Jakarta Server Pages、 Jakarta Expression Language、 Jakarta WebSocket、 Jakarta Annotations和 Jakarta Authentication 规范的开源实现 。Apache Tomcat实现了对Servlet和JavaServer Page(JSP&#xff09…

Kong 服务和路由的添加

管理服务 这里参考DB-less-Mode,因为使用的是yaml配置文件的形式,所以所有的相关配置只需要往初始化的kong.yml文件中添加就可以了,就像nginx的配置文件 DB-less-Mode 创建服务 vim /etc/kong/kong.yml services: - name: my-service #…

flutter开发实战-底部bottomNavigationBar➕PageView

flutter开发实战-底部bottomNavigationBar tabbar在app中非常常见,底部BottomNavigationBar属性 一、BottomNavigationBar属性 BottomNavigationBar组件的常用属性: type:tabbar样式,默认为白色不显示;fixedColor:t…