设计模式(十)----结构型模式之适配器模式

news2024/9/23 17:16:05

1、概述

如果去欧洲国家去旅游的话,他们的插座如下图最左边,是欧洲标准。而我们使用的插头如下图最右边的。因此我们的笔记本电脑,手机在当地不能直接充电。所以就需要一个插座转换器,转换器第1面插入当地的插座,第2面供我们充电,这样使得我们的插头在当地能使用。生活中这样的例子很多,手机充电器(将220v转换为5v的电压),读卡器等,其实就是使用到了适配器模式。

定义:

将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

2、结构

适配器模式(Adapter)包含以下主要角色:

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。上图中的最右边插口

  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。上图中的最左边插口

  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

3、类适配器模式

实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。

【例】读卡器

现有一台电脑只能读取SD卡,而要读取TF卡中的内容的话就需要使用到适配器模式。创建一个读卡器,将TF卡中的内容读取出来。

类图如下:

代码如下:

//SD卡的接口
public interface SDCard {
    //读取SD卡方法
    String readSD();
    //写入SD卡功能
    void writeSD(String msg);
}
​
//SD卡实现类
public class SDCardImpl implements SDCard {
    public String readSD() {
        String msg = "sd card read a msg :hello word SD";
        return msg;
    }
​
    public void writeSD(String msg) {
        System.out.println("sd card write msg : " + msg);
    }
}
​
//电脑类
public class Computer {
​
    public String readSD(SDCard sdCard) {
        if(sdCard == null) {
            throw new NullPointerException("sd card null");
        }
        return sdCard.readSD();
    }
}
​
//TF卡接口
public interface TFCard {
    //读取TF卡方法
    String readTF();
    //写入TF卡功能
    void writeTF(String msg);
}
​
//TF卡实现类
public class TFCardImpl implements TFCard {
​
    public String readTF() {
        String msg ="tf card read msg : hello word tf card";
        return msg;
    }
​
    public void writeTF(String msg) {
        System.out.println("tf card write a msg : " + msg);
    }
}
​
//定义适配器类(SD兼容TF)
public class SDAdapterTF extends TFCardImpl implements SDCard {
​
    public String readSD() {
        System.out.println("adapter read tf card ");
        return readTF();
    }
​
    public void writeSD(String msg) {
        System.out.println("adapter write tf card");
        writeTF(msg);
    }
}
​
//测试类
public class Client {
    public static void main(String[] args) {
        Computer computer = new Computer();
        SDCard sdCard = new SDCardImpl();
        System.out.println(computer.readSD(sdCard));
​
        System.out.println("===============");
​
        SDAdapterTF adapter = new SDAdapterTF();
        System.out.println(computer.readSD(adapter));
    }
}

测试结果

类适配器模式违背了合成复用原则。类适配器是客户类有一个接口规范的情况下可用,反之不可用。

4、对象适配器模式

实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口。

【例】读卡器

我们使用对象适配器模式将读卡器的案例进行改写。类图如下:

代码如下:

类适配器模式的代码,我们只需要修改适配器类(SDAdapterTF)和测试类。

//创建适配器对象(SD兼容TF)
public class SDAdapterTF  implements SDCard {
​
    private TFCard tfCard;
​
    public SDAdapterTF(TFCard tfCard) {
        this.tfCard = tfCard;
    }
​
    public String readSD() {
        System.out.println("adapter read tf card ");
        return tfCard.readTF();
    }
​
    public void writeSD(String msg) {
        System.out.println("adapter write tf card");
        tfCard.writeTF(msg);
    }
}
​
//测试类
public class Client {
    public static void main(String[] args) {
        Computer computer = new Computer();
        SDCard sdCard = new SDCardImpl();
        System.out.println(computer.readSD(sdCard));
​
        System.out.println("------------");
​
        TFCard tfCard = new TFCardImpl();
        SDAdapterTF adapter = new SDAdapterTF(tfCard);
        System.out.println(computer.readSD(adapter));
    }
}

注意:还有一个适配器模式是接口适配器模式。当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可。

5、应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。

  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

6、JDK源码解析

Reader(字符流)、InputStream(字节流)的适配使用的是InputStreamReader。

InputStreamReader继承自java.io包中的Reader,对他中的抽象的未实现的方法给出实现。如:

public int read() throws IOException {
    return sd.read();
}
​
public int read(char cbuf[], int offset, int length) throws IOException {
    return sd.read(cbuf, offset, length);
}

如上代码中的sd(StreamDecoder类对象),在Sun的JDK实现中,实际的方法实现是对sun.nio.cs.StreamDecoder类的同名方法的调用封装。类结构图如下:

从上图可以看出:

  • InputStreamReader是对同样实现了Reader的StreamDecoder的封装。

  • StreamDecoder不是Java SE API中的内容,是Sun JDK给出的自身实现。但我们知道他们对构造方法中的字节流类(InputStream)进行封装,并通过该类进行了字节流和字符流之间的解码转换。

结论:

从表层来看,InputStreamReader做了InputStream字节流类到Reader字符流之间的转换。而从如上Sun JDK中的实现类关系结构中可以看出,是StreamDecoder的设计实现在实际上采用了适配器模式。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

以太网详细解析

数据链路层:考虑相邻两个节点之间的传输(通过网线/光纤/无线直接相连的两个设备) 这里以数据链路层其中最知名的就是“以太网” 以太网帧格式: 以太网数据帧帧头载荷帧尾 帧头:目的地址、源地址、类型 目的地址和源…

51单片机简易电阻电感电容RLC测量仪仿真设计

51单片机简易电阻电感电容RLC测量仪仿真( proteus仿真程序讲解视频) 仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0040 51单片机简易电阻电感电容RLC测量仪仿真51单片机最小系统的相关知识复位…

【第二阶段:java基础】第13章:泛型(P553-P568):自定义泛型、泛型的集成和通配符、Junit

本系列博客是韩顺平老师java基础课的课程笔记,B站:课程链接,吐血推荐的一套全网最细java教程,获益匪浅! 韩顺平P553-P5681. 泛型的理解和好处2. 泛型的定义3. 泛型的语法4. 泛型的细节5. 自定义泛型6. 泛型继承和通配符…

62 一次 Promotion failed 的调试

前言 最近 有一个想法就是, 调试一下 DefNewGeneration 里面的晋升失败的情况 呵呵 对于这块的代码上面, 看着感觉有一些疑问的地方, 因此想通过 实际的调试, 来验证一下 实际的情况 然后 之前写了一个用例, 但是 和心中的期望差距甚大, 当然 主要的问题 还是自己对于 细…

CSDN 算法技能树 蓝桥杯-基础 刷题+思考总结

切面条-蓝桥杯-基础-CSDN算法技能树https://edu.csdn.net/skill/algorithm/algorithm-530255df51be437b967cbc4524fe66ea?category188 目录 切面条 大衍数列 门牌制作 方阵转置 微生物增殖 成绩统计 星系炸弹 判断闰年的依据: 特别数的和 *日志统计*(双指…

结构体与引用

1.结构体基本概念结构体属于用户自定义的数据类型,允许用户存储不同的数据类型2.结构体定义和使用语法: struct 结构体 { 结构体成员列表 };通过结构体创建变量的方式有三种:struct 结构体名 变量名struct 结构体名 变量名 { 成员1值,成员2值...}定义结构…

《爆肝整理》保姆级系列教程python接口自动化(十八)--重定向(Location)(详解)

简介   在实际工作中,有些接口请求完以后会重定向到别的url,而你却需要重定向前的url。URL主要是针对虚拟空间而言,因为不是自己独立管理的服务器,所以无法正常进行常规的操作。但是自己又不希望通过主域名的二级目录进行访问&…

分布式session共享解决方案

分布式session共享解决方案 1.分布式 Session 问题 示意图 解读上图,假如我们去购买商品 当 Nginx 对请求进行负载均衡后, 可能对应到不同的 Tomcat比如第 1 次请求, 均衡到 TomcatA, 这时 Session 就记录在 TomcatA, 第 2 次请求, 均衡到 TomcatB, 这…

【Mysql8.0取消严格区分大小】已安装的mysql8.0取消严格区分大小写及mysql8.0重装与赋权限详解(2023年亲测有效)

【写在前面】其实故事要从my.cnf为空,且lower-case-table-names为0开始,linux环境下mysql8.0及其之后的版本对表名和数据库是严格区分大小写的,从而导致我们运行项目时候会报错Table xxx.QRTZ_LOCKS doesnt exist。但是我已经装好了mysql8.0咋…

17.CSS伪类

举一个简单的例子来说明什么是伪类&#xff1f; 从之前的代码中&#xff0c;如下图&#xff0c;我们像给这两个列表中的某一列单独设置样式&#xff0c;我们该如何做呢&#xff1f; 我们肯定会选择在li标签上添加class去实现&#xff0c;如下 开始标记结束标记实际元素 <…

python--matplotlib(2)

前言 Matplotlib画图工具的官网地址是 http://matplotlib.org/ Python环境下实现Matlab制图功能的第三方库&#xff0c;需要numpy库的支持&#xff0c;支持用户方便设计出二维、三维数据的图形显示&#xff0c;制作的图形达到出版级的标准。 实验环境 Pycharm2020.2.5社区版,w…

算法练习-链表(二)

算法练习-链表&#xff08;二&#xff09; 文章目录算法练习-链表&#xff08;二&#xff09;1. 奇偶链表1.1 题目1.2 题解2. K 个一组翻转链表2.1 题目2.2 题解3. 剑指 Offer 22. 链表中倒数第k个节点3.1 题目3.2 题解3.2.1 解法13.2.2 解法24. 删除链表的倒数第 N 个结点4.1 …

中国智能物流行业市场规模及未来发展趋势

中国智能物流行业市场规模及未来发展趋势编辑中国智能物流行业市场规模正在快速增长。随着电子商务、物流配送、物联网等行业的发展&#xff0c;物流行业需求不断提高&#xff0c;智能物流产品应运而生。智能物流行业主要通过智能化管理、智能路径规划、智能定位、物流配送等方…

Java特性之设计模式【工厂模式】

一、工厂模式 概述 工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式 在工厂模式中&#xff0c;我们在创建对象时不会对客户端暴露创建逻辑&#xff0c;并且是通…

投票需要什么流程微信投票互助平台的免费投票平台搭建

“最美家政人”网络评选投票_免费小程序投票推广_小程序投票平台好处手机互联网给所有人都带来不同程度的便利&#xff0c;而微信已经成为国民的系统级别的应用。现在很多人都会在微信群或朋友圈里转发投票&#xff0c;对于运营及推广来说找一个合适的投票小程序能够提高工作效…

Java-集合(5)

Map接口 JDK8 Map接口实现子类的特点 Map和Collection是并列关系&#xff0c;Map用于保存具有映射关系的数据&#xff1a;Key-ValueMap中的key和value可以是任何引用类型的数据&#xff0c;会封装到HashMap$Node对象中Map中的key不允许重复&#xff0c;原因和HashSet一样Map…

2023年美赛MCM 问题C:预测Wordle结果 ​

目录2023年美赛MCM 问题C: 预测Wordle结果 ​1. 背景2. 要求3. 附件1. 数据文件。2. 纽约时报网站上发布的 Wordle 指南4. 参考2023年美赛MCM 问题C: 预测Wordle结果 ​ 1. 背景 Wordle 是纽约时报目前每天提供的流行拼图。 玩家尝试通过在六次或更少的尝试中猜测一个五个字母…

记录一次Binder内存相关的问题导致APP被杀的BUG排查过程

事情的起因的QA压测过程发生进程号变更&#xff0c;怀疑APP被杀掉过&#xff0c;于是开始看日志 APP的压测平台会上报进程号变更时间点&#xff0c;发现是在临晨12&#xff1a;20分&#xff0c;先大概确定在哪个日志文件去找关键信息一开始怀疑是crash&#xff0c;然后就在日志…

shiro CVE-2020-1957

0x00 前言 在之前只是单纯的复现了漏洞&#xff0c;没有记笔记&#xff0c;所以补充了这篇分析笔记。 影响版本&#xff1a;shiro < 1.5.2 0x01 环境搭建 环境用的是&#xff1a;https://github.com/lenve/javaboy-code-samples/tree/master/shiro/shiro-basic 0x02 漏…

用python实现对AES加密的视频数据流解密

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法。 在做网络爬虫的时候,会遇到经过AES加密的数据,可以使用python来进行解密。 在做爬虫的时候,通常可以找到一个key,这个key是一个十六进制的一串字符,这传字符是解密的关键。所以对于…