【设计模式】适配器模式 (七)

news2025/2/6 11:49:25

文章目录

    • 5.2 适配器模式
      • 5.2.1 概述
      • 5.2.2 结构
      • 5.2.3 类适配器模式
      • 5.2.4 对象适配器模式
      • 5.2.5 应用场景
      • 5.2.6 JDK源码解析

5.2 适配器模式

5.2.1 概述

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

在这里插入图片描述

定义:

​ 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
简单来说就是,有一个方法需要实现,但是需要调用另外一个类的方法来实现。

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

5.2.2 结构

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

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

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

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

5.2.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.2.5 应用场景

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

5.2.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/102923.html

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

相关文章

机器学习笔记之玻尔兹曼机(一)基本介绍

机器学习笔记之玻尔兹曼机——基本介绍引言回顾:玻尔兹曼机的模型表示模型参数的对数似然梯度关于模型参数W\mathcal WW的对数似然梯度关于模型参数L,J\mathcal L,\mathcal JL,J的对数似然梯度引言 在受限玻尔兹曼机——模型表示(Representation)一节中以玻尔兹曼机…

五环三萜类化合物环糊精包合物前体脂质体/呋喃硫胺/6已基环糊精纳米粒制备

小编在这里为大家分享的是五环三萜类化合物环糊精包合物前体脂质体/呋喃硫胺/6已基环糊精纳米粒,一起来看看吧! 五环三萜类化合物环糊精包合物前体脂质体制备方法: 通过环糊精将五环三萜类化合物包合提高亲水性,并以脂质体为载体进行包覆,通…

[Linux]线程概念_线程控制(线程与进程的区别与联系 | 线程创建 | 线程等待 | 线程终止 | 线程分离 | LWP)

文章目录线程概念进程和线程的关系线程的优点线程的缺点线程控制Linux线程和接口关系的认识线程创建线程ID及进程地址空间布局线程等待线程终止线程终止状态线程分离LWP和pthread_t线程概念 线程是在进程内部运行的一个执行分支(执行流),属于…

我会用12种编程语言,但是偏爱python,看完文章你就知道原因了

刚开始学编程,或者学习一门新的编程语言时,我们编写的第一个程序往往很简单,而且往往这个程序就是输出一个简单的文本。在阅读本文时,你可能心知肚明我指的是哪种最常见的文本。 没错,我说的就是 Hello world。 这段文…

当中医遇上AI,贝叶斯携手昇思打造AI舌诊联合方案

中医的困局 中医迄今已有数千年历史,是老祖宗留给我们最宝贵的财富之一。然而,随着近代医学技术的发展,与声势浩大的西医相比,中医逐渐失势。 近年来,人口老龄化导致慢性病发病率持续增高。国家层面出台《健康中国行…

生态类型 or 生境类型?16S全长测序判断河流中细菌群落构建机理

文献标题: Distinct composition and assembly processes of bacterial communities in a river from the Arid area: Ecotypes or Habitat Types? 研究背景 细菌群落在河流生态系统中起着重要的作用,如元素循环和有机物的降解等。对河流细菌群落的扰…

基于实时迭代的数值鲁棒NMPC双模稳定预测模型(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

还在用明文存储密码吗?快来了解一下加密吧

目录 一. 数据库为什么不能明文存储密码 二. MD5到底是什么? 2.1 MD5概述 2.2 MD5为什么不是加密算法? 2.3 MD5主要特点MD5 2.4 MD5的性质 2.5 为什么用MD5存储密码不好 三. 给密码加盐再落库,增加破解成本 四. BCrypt算法加密解密…

零入门容器云网络-8:网络虚拟设备之tun设备介绍

已发表的技术专栏(订阅即可观看所有专栏) 0  grpc-go、protobuf、multus-cni 技术专栏 总入口 1  grpc-go 源码剖析与实战  文章目录 2  Protobuf介绍与实战 图文专栏  文章目录 3  multus-cni   文章目录(k8s多网络实现方案) 4  gr…

SpringCloud(8)— 使用ElasticSearch(RestClient)

SpringCloud(8)— 使用ElasticSearch(RestClient) 一 认识RestClient ES 官方提供了各种语言的客户端用来操作ES,这些客户端的本质就是组创DSL语句,通过 Http 请求发送给ES 官方文档地址:Elasticsearch Clients | E…

运维基础(上部)

运维基础【(上部)】 因为笔记所记内容太多,所以我分成了上下两部分来分享给大家查看学习!同时我会持续更新博客发布更加优质的文章,希望大家多多支持与关注!感谢! 一、运维概述 1、运维岗位的收…

[附源码]计算机毕业设计Python港口集团仓库管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等…

GitLab Runner的使用

一、初次使用GitLab Runner 特别说明:前面已经将本地项目成功推送到了GitLab中,并且已经注册了一个GitLab Runner,接下来就是使用GitLab Runner。 触发GitLab Runner以完成GitLab的CI(持续集成)/CD(持续部署),需满足下述两个条件: 仓库根目录下面存在有.gitlab-ci.yml文…

[ Linux ] 互斥量实现原理,线程安全

上篇文章我们对抢票系统做了加锁处理,对互斥量tickets进行加锁。而本篇博文来谈谈互斥量实现的原理以及相关问题。 目录 1.上篇遗留问题 我们在临界资源对应的临界区中加锁了,就不是多行代码了吗?如果还是多行代码,难道不会被切…

[附源码]计算机毕业设计Python公益组织登记与查询系统论文(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

【AI with ML】第 13 章 :在 Android 应用程序中使用 TensorFlow Lite

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

vue的虚拟DOM和diff算法

虚拟DOM和diff算法密不可分, 虚拟dom,它本身就是一个 JavaScript 对象,为解决DOM操作非常耗时,把DOM转换为虚拟DOM,DOM操作转换为js计算,js执行速度较快。 diff算法在vue中被优化为O(n)的时间复杂度&#x…

手机损坏的数据导出方法

主板损坏的症状 手机主板损坏的症状表现一般为系统启动失败、屏幕无显示、启动黑屏死机、无法开机、没有声音、无法打电话、没网络等等。 资料的重要性 手机坏了,怎么把手机里面重要的资料导出来?今天小编就来跟大家说说手机导资料这个事。 手机坏了,具体要看手机是哪里…

java计算机毕业设计ssm基于JavaWeb的公务员招考信息发布平台

项目介绍 随着互联网技术的发发展,计算机技术广泛应用在人们的生活中,逐渐成为日常工作、生活不可或缺的工具,各种管理系统层出不穷。公务员是各国负责统筹管理经济社会秩序和国家公共资源,维护国家法律规定,贯彻执行相关义务的公职人员。每年报考公务员的人数逐渐增加,特为此…

寒假训练营 第一节 时空复杂度分析

一.时空复杂度的分析 1.时间复杂度 时间复杂度&#xff1a;程序运行会消耗多少时间。 在此&#xff0c;为了方便讨论&#xff0c;我们假定每一个语句消耗的时间一样&#xff0c;视为一个时间单元。 #include <iostream> using namespace std; int main() {int n 100;…