第七章结构性模式—适配器模式

news2024/10/7 14:26:39

文章目录

  • 适配器模式
    • 解决的问题
    • 概念
    • 结构
  • 类适配器模式
  • 对象适配器模式
  • 接口适配器模式
  • 应用场景
    • JDK 源码 - Reader 与 InputStream

结构型模式描述如何将类或对象按某种布局组成更大的结构,有以下两种:

  • 类结构型模式:采用继承机制来组织接口和类。
  • 对象结构型模式:釆用组合或聚合来组合对象。

由于组合关系或聚合关系比继承关系耦合度低,满足 “合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。

结构型模式分为以下 7 种:

  • 代理模式
  • 适配器模式
  • 装饰者模式
  • 桥接模式
  • 外观模式
  • 组合模式
  • 享元模式

适配器模式

解决的问题

img

  • 比如我们插头的电流和手机需要的电流是不一样的,我们不能直接使用,所以需要充电器来转换电流,我们的充电器就是类似适配器,将两个不兼容的东西兼容到一起用
  • 也比如我们的聋哑人是不能听到我们说话的,手语翻译员将我们的话翻译为手语,然后聋哑人可以“听懂我们说话”,手语翻译员就是我们的适配器

概念

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

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

结构

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

  • 目标(Target)接口:当前系统业务所期望访问的接口,它可以是抽象类或接口。
  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
    • 适配者类,其实是要被适配到目标接口的类。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

类适配器模式

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

  • 实现业务接口,继承已有组件

【例】读卡器

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

创建一个读卡器,将 TF 卡中的内容读取出来,类图如下:

image-20230504092203455

  • SDCard 是目标接口,它是 Computer 所期望访问的接口
  • TFCard 是适配者类,它将会被适配到 Computer 可以访问的 SDCard
  • SDAdapterTF 是适配器类,它实现让目标访问 SDCard 却达到 TFCard 的功能。

目标接口—SDCard和其实现类

public interface SDCard {
    String readSD();
    // 往SD卡中写数据
    void writeSD(String msg);
}
public class SDCardImpl implements SDCard{
    @Override
    public String readSD() {
        String msg = "sd card read a msg :hello word SD";
        return msg;
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("sd card write msg : " + msg);
    }
}

适配者接口—TFCard和其实现类

public interface TFCard {
    public String readTF();
    public void writeTF(String msg);
}
public class TFCardImpl implements TFCard{
    @Override
    public String readTF() {
        String msg = "TFCard read msg: hello word TFCard";
        return msg;
    }

    @Override
    public void writeTF(String msg) {
        System.out.println("TFCard write msg: " + msg);
    }


}

适配器类

public class SDAdapterTF extends TFCardImpl implements SDCard{
    @Override
    public String readSD() {
        System.out.println("adapter read tf card");
        return readTF();
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("adapter write tf card");
        writeTF(msg);
    }
}
  • 继承我们的适配者实现类和实现其目标接口
    • 继承我们的适配者实现类是为了能够调用其中的对应的方法
    • 实现其目标接口是为了起到适配的效果

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

对象适配器模式

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

实现业务接口,引入已有组件

改造后的适配器类

public class SDAdapterTF implements SDCard {
    private TFCard tfCard;

    public SDAdapterTF(TFCard tfCard) {
        this.tfCard = tfCard;
    }

    @Override
    public String readSD() {
        System.out.println("adapter read tf card");
        return tfCard.readTF();
    }

    @Override
    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();
        // 电脑读取SD卡中的数据(可直接读)
        String msg = computer.readSD(new SDCardImpl());
        System.out.println(msg);

        System.out.println("===============");
        // 使用电脑读取TF卡中的数据(无法直接读)
        // 创建适配器类对象
        SDAdapterTF sdAdapterTF = new SDAdapterTF(new TFCardImpl());
        String s = computer.readSD(sdAdapterTF);
        System.out.println(s);
    }
}
  • 通过构造方法来给适配器传入对应的适配者类的实例对象

接口适配器模式

当不希望实现一个接口中所有的方法时,可以创建一个抽象类 Adapter 实现接口所有方法,然后只需要继承该抽象类即可。

应用场景

  • 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
  • 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。

JDK 源码 - Reader 与 InputStream

  • 解码:字节数据 -> 字符数据
  • 编码:字符数据 -> 字节数据

image-20230504103651731

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);
}

从上图可以看出:

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

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

结论:

  • 表面看,InputStreamReader 做了 InputStream 字节流类到 Reader 字符流之间的转换。
  • 而从如上 Sun JDK 中的实现类关系结构中可以看出,是 StreamDecoder 在设计实现上采用了适配器模式。
    • StreamDecoder 就是对应的适配器类
    • Reader是对应的目标接口,只是这里不是接口,而是对应的抽象方法
    • InputStream是对应的适配类,在我们StreamDecoder中聚合了对应的适配类对象,也就是对应的对象适配器模式

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

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

相关文章

AUTOSAR-MemIf

1、MemIf的功能 从AUTOSAR的架构图中可以看出,MemIf(Memory Abstraction Interface)模块位于Memory Hardware Abstraction。  一方面,NvM使用MemIf提供的接口访问NV memory(NV memory分为两种:Flash和EEPROM,位于MCAL…

APP图标尺寸规范一文了解清楚

在进行图标设计前,熟知手机 app 图标尺寸规范,能更好地去针对不同平台设计出更极致的图标。当前智能手机系统主要以 iOS 及 Android 为主,APP 图标是产品给用户的第一印象,图标视觉设计的美感与吸引力,与用户是否选择下…

分子模拟力场

分子模拟力场 AMBER力场是在生物大分子的模拟计算领域有着广泛应用的一个分子力场。开发这个力场的是Peter Kollman课题组,最初AMBER力场是专门为了计算蛋白质和核酸体系而开发的,计算其力场参数的数据均来自实验值,后来随着AMBER力场的广泛…

冷链保温箱在冷链中扮演了什么角色?

冷链运输是指某些食品原料、经过加工的食品或半成品、特殊的生物制品在经过收购、加工、灭活后,在产品加工、贮藏、运输、分销和零售、使用过程中,其各个环节始终处于产品所必需的特定低温环境下,减少损耗,防止污染和变质&#xf…

如何用私域流量让不知名新品牌大放异彩……

说到不知名品牌,那minayo这个品牌应该绝大部分人都没听说过,因为他从诞生到今天也就刚刚一年的时间。 minayo是一家功能性食品品牌,专注于美容类健康食品领域,主要为用户提供 AG 饮料、植物酵素、美白片、胶原蛋白果冻等产品。 …

基于区域的图像分割

文章目录 基于区域的图像分割基本原理常用的算法实现步骤示例代码结论 基于区域的图像分割 基于区域的图像分割是数字图像处理中常用的一种方法,它通过将图像中的像素分配到不同的区域或对象来实现图像分割的目的。相比于基于边缘或阈值的方法,基于区域…

汉明码奇偶校验矩阵理解

首先看 汉明码 一、矩阵解释 单bit纠正( SEC,single error correction ) 以数据位为8位(m)为例,编码位数为r,2^r>mr1 r最小为4 编码后位数为4812位 编码位为p1,p2 ,p3, p4 p1掌控&#xff…

数据分析真的很火吗?真的有很多企业需要这样的岗位吗?求大佬指点。

“我是去年毕业的,因为疫情影响,整个就业环境都很不好,很多企业都裁员了。加上疫情三年基本都是玩过去,也没啥一技之长,就业就更难了。听说现在做数据分析的人很多,我身边的朋友都在转行做数据分析。 其实…

【2023/05/15】Rust

Hello!大家好,我是霜淮子,2023倒计时第10天。 Share Rest belongs to the work as the eyelids to the eyes. 译文: 休息与工作的关系,正如眼睑与眼睛的关系。 Man is a born child,his power is the power of gro…

华为od题库汇总分享

​ 前言 最近有很多群友问塔子哥华为最新OD题库在哪里可以找。我索性就写篇文章介绍一下吧~。这里塔子哥还是要说一下,大家想进华为od还是要重视题库。因为根据无数群友,网友的反映。华为od就是从题库里抽题,不会有新题。只是每个季度题库会…

使用mapbox+turf.js完成迁徙图,流向图教程

以前对于迁徙图流向图这样的需求大多都是采用echarts这样的图标组件库做的。这篇文章跟大家分享一下如何使用webgis的技术方式实现迁徙图,流向图这样的专题地图。 首先我们要把思路捋清楚,迁徙图表示的是从一个点出发向多个点均有流向(这个流向用线条表示)或者是从多个地方…

利用GPU并行计算beta-NTI,大幅减少群落构建计算时间

1 先说效果 18个样本,抽平到8500条序列,4344个OTUs,计算beta-NTI共花费时间如下。如果更好的显卡,更大的数据量,节约的时间应该更加可观。 GPU(GTX1050):1分20秒 iCAMP包 的bNTIn.p(…

你可能不需要「那么」担心,人工智能对你的工作造成威胁

大家好,我是可夫小子,关注AIGC、读书和自媒体。解锁更多ChatGPT、AI绘画玩法。加:keeepdance,备注:chatgpt,拉你进群。 上周,AI似乎成为全互联网的焦点了。谷歌在2023IO开发者大会上&#xff0c…

MySQL之B+树索引的使用

前言 本文章收录在MySQL性能优化原理实战专栏,点击此处查看更多优质内容。 本文摘录自 ▪ 小孩子4919《MySQL是怎样运行的:从根儿上理解MySQL》 我们上一篇文章详细的了InnoDB存储引擎的B树索引,我们必须知道下边这些结论: 每个…

如何快速入门网络安全?

前言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了.2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发.3.有时多 google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答.4.遇到实在搞不懂的,可以先放放,以后再来解决. 学习网…

企业级信息系统开发讲课笔记4.2 Spring Boot项目单元测试、热部署与原理分析

文章目录 零、学习目标一、Spring Boot单元测试(一)Spring Boot单元测试概述(二)对项目HelloWorld01进行单元测试1、修改pom.xml文件,添加测试依赖启动器和单元测试2、创建测试类与测试方法 (三&#xff09…

CMAKE介绍和使用(Windows平台)

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。 Windows平台 cmake工具的下载 cmake工具下载官网: Download | CMake 下载压缩包后解压,解压后的bin文件路径加到电脑系统环境…

ANR基础篇 - 相关系统知识简介

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言一、CPU相关知识1.CPU核心架构大小核架构 2.绑核3.锁频4.CPU状态 二、线程状态1.R…

自学黑客(网络安全)如何入门?收藏这篇就够了

前言: 趁着今天下班,我花了几个小时整理了下,非常不易,希望大家可以点赞收藏支持一波,谢谢。 我的经历: 我19年毕业,大学专业是物联网工程,我相信很多人在象牙塔里都很迷茫&#x…

阿里18k的外包能去吗?

有挺多测试员曾在BAT、网易这些大厂做过外包,想必大家也是非常关心此类问题,我就想介绍下“什么是外包?”,“外包公司的现状”,就“为什么这么多人鄙视外包测试岗?”、”阿里18K的外包测试岗能去吗&#xf…