适配器模式介绍

目录

一、适配器模式介绍

1.1 适配器模式定义

1.2 适配器模式原理

1.2.1 适配器模式类图

1.2.2 模式角色说明

二、适配器模式的应用

2.1 类适配器模式

2.1.1 需求说明

2.1.2 需求实现

2.1.2.1 类图

2.1.2.2 具体实现

2.1.2.2.1 SDCard接口

2.1.2.2.2 SDCardImpl实现类

2.1.2.2.3 TFCard接口

2.1.2.2.4 TFCardImpl 实现类

2.1.2.2.5 SDAdapterTF适配类

2.1.2.2.6 Computer接口调用类

2.1.2.2.7 测试类

2.2 对象适配器模式

2.2.1 需求说明

2.2.2 需求实现

2.2.2.1 类图

2.2.2.2 具体实现

2.2.2.2.1 适配器实现类

2.2.2.2.2 测试类

三、适配器模式总结

3.1 适配器模式的优点

3.2 适配器模式的缺点

3.3 适配器模式适用的场景

3.4 代理、桥接、装饰器、适配器 4 种设计模式的区别


一、适配器模式介绍

1.1 适配器模式定义

适配器模式(adapter pattern )的原始定义是:将类的接口转换为客户期望的另一个接口,适配器可以让不兼容的两个类一起协同工作。

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

适配器模式是用来做适配,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。类适配器模式的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

1.2 适配器模式原理

1.2.1 适配器模式类图

1.2.2 模式角色说明

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

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

二、适配器模式的应用

2.1 类适配器模式

2.1.1 需求说明

假设现有一台电脑目前只能读取SD卡的信息,这时我们想要使用电脑读取TF卡的内容, 就需要将TF卡加上卡套,转换成SD卡!

2.1.2 需求实现

2.1.2.1 类图

2.1.2.2 具体实现
2.1.2.2.1 SDCard接口
package main.java.cn.test.adapter.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:07:50
 * @description SD卡接口
 */
public interface SDCard {
    //读取SD卡方法
    String readSD();

    //写入SD卡功能
    void writeSD(String msg);
}

2.1.2.2.2 SDCardImpl实现类
package main.java.cn.test.adapter.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:08:21
 * @description SD卡实现类
 */
public class SDCardImpl implements SDCard {
    @Override
    public String readSD() {
        String msg = "sd card reading data";
        return msg;
    }

    @Override
    public void writeSD(String msg) {
        System.out.println("sd card write data : " + msg);
    }
}
2.1.2.2.3 TFCard接口
package main.java.cn.test.adapter.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:09:15
 * @description TF卡接口
 */
public interface TFCard {
    //读取TF卡方法
    String readTF();

    //写入TF卡功能
    void writeTF(String msg);
}
2.1.2.2.4 TFCardImpl 实现类
package main.java.cn.test.adapter.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:09:47
 * @description TF卡实现类
 */
public class TFCardImpl implements TFCard {
    @Override
    public String readTF() {
        String msg = "tf card reading data";
        return msg;

    }

    @Override
    public void writeTF(String msg) {
        System.out.println("tf card write data : " + msg);

    }
}

2.1.2.2.5 SDAdapterTF适配类
package main.java.cn.test.adapter.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:10:29
 * @description 定义适配器类(SD兼容TF)
 */
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);
    }
}

2.1.2.2.6 Computer接口调用类
package main.java.cn.test.adapter.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:13:15
 * @description
 */
public class Computer{
    public String read(SDCard sdCard) {
        return sdCard.readSD();
    };
}

2.1.2.2.7 测试类
package main.java.cn.test.adapter.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:11:39
 * @description 测试类
 */
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        SDCard sdCard = new SDCardImpl();
        System.out.println(computer.read(sdCard));
        System.out.println("========================");
        SDAdapterTF adapterTF = new SDAdapterTF();
        System.out.println(computer.read(adapterTF));
    }
}

2.2 对象适配器模式

2.2.1 需求说明

假设现有一台电脑目前只能读取SD卡的信息,这时我们想要使用电脑读取TF卡的内容, 就需要将TF卡加上卡套,转换成SD卡! 适用对象适配器模式实现。

2.2.2 需求实现

2.2.2.1 类图

2.2.2.2 具体实现
2.2.2.2.1 适配器实现类
package main.java.cn.test.adapter.V2;

import main.java.cn.test.adapter.V1.SDCard;
import main.java.cn.test.adapter.V1.TFCard;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:31:54
 * @description 定义适配器类(SD兼容TF)
 */
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);

    }
}

2.2.2.2.2 测试类
package main.java.cn.test.adapter.V2;

import main.java.cn.test.adapter.V1.*;

/**
 * @author ningzhaosheng
 * @date 2024/1/14 12:33:18
 * @description
 */
public class Test2 {
    public static void main(String[] args) {
        Computer computer = new Computer();
        SDCard sdCard = new SDCardImpl();
        System.out.println(computer.read(sdCard));
        System.out.println("========================");
        TFCard tfCard = new TFCardImpl();
        SDAdapterTF adapterTF = new SDAdapterTF(tfCard);
        System.out.println(computer.read(adapterTF));
    }
}

三、适配器模式总结

3.1 适配器模式的优点

1. 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无序修改原有结构
2. 增加了类的透明性和复用性,将具体业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
3. 灵活性和扩展性都非常好,通过使用配置文件可以很方便的更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,符合开闭原则。

3.2 适配器模式的缺点

  • 类适配器的缺点
  1. 对于Java等不支持多重继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者
  2. 适配者类不能为最终类
  • 对象适配器的缺点
  1. 与类适配器模式相比较,在该模式下要在适配器中置换适配者类的某些方法比较麻烦。

3.3 适配器模式适用的场景

  • 统一多个类的接口设计时

某个功能的实现依赖多个外部系统(或者说类)。通过适配器模式,将它们的接口适配为统一的接口定义

  • 需要依赖外部系统时

当我们把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可以减少对代码的改动

  • 原有接口无法修改时或者原有接口功能太老旧但又需要兼容;

JDK1.0 Enumeration 到 Iterator 的替换,适用适配器模式保留Enumeration 类,并将其实现替换为直接调用 Itertor。

  • 适配不同数据格式时;

Slf4j 日志框架,定义打印日志的统一接口,提供针对不同日志框架的适配器

3.4 代理、桥接、装饰器、适配器 4 种设计模式的区别

代理、桥接、装饰器、适配器,这 4 种模式是比较常用的结构型设计模式。它们的代码结构非常相似。但其各自的用意却不同,简单说一下它们之间的关系。

  • 代理模式:

代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同。

  • 桥接模式:

桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地加以改变。

  • 装饰器模式:

装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用。

  • 适配器模式:

将一个类的接口转换为客户希望的另一个接口.适配器模式让那些不兼容的类可以一起工作。

好了,本次分享就到这里,欢迎大家继续阅读《设计模式》专栏其他设计模式内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

婴儿洗衣机哪款性价比高?希亦、RUUFFY、觉飞全维度测评对比

当婴儿的到来,确实会给家庭带来许多变化,就好比如对于宝宝相关衣物的清洗需求。对于新生儿及婴幼儿的衣服,一般都要给予特殊的照顾与清洗,以保证不含细菌及过敏原。尤其是刚刚出生的婴儿,这时候宝宝们的皮肤很是幼嫩。…

【JavaEE进阶】 利用Spring简单实现加法计算器和用户登录

文章目录 🎍序言🌳加法计算器🚩准备工作🚩约定前后端交互接⼝🌲后端服务器代码的书写 🌴用户登录🚩效果展示🚩准备工作🚩约定前后端交互接⼝🎈需求分析&#…

spring boot学习第八篇:kafka

目录 1、安装kafka 1.1确认jdk是否安装OK 1.2下载kafka 1.3安装kafka 1.4验证kafka 2、连接kafka 3、在java中操作kafka 1、安装kafka 1.1确认jdk是否安装Ok java -version 1.2下载kafka wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-…

K8S之configMapsecret

job 第一个是初始化尝试,初始化尝试失败之后,会再重试两次。 配置资源管理: Secret Configmap*:1.2加入的新特征 1.18 Secret: 保存密码,token,敏感的k8s资源 这类数据可以存放在镜像当中,但是防止secret当中可以更方便的控…

爬虫—根据股票代码实时抓取股票信息

爬虫—根据股票代码实时抓取股票信息 数据来源网址:https://xueqiu.com 目标:根据输入的股票代码和证券所,实时抓取股票的交易信息 源码如下: import requests from lxml import etree# 本案例数据需要账号登录之后才能获取&a…

MSSQL-识别扩展extended event(扩展事件)中的时间单位

经常使用sqlserver extended event(扩展事件),但是总是忘记扩展事件使用的时间单位,不确定它们是 秒、毫秒、还是微秒? 以下下代码能够从 相关DMV中提取description字段内容来识别时间单位: SELECT [p].[name] [package_name],[o…

Androidmanifest文件加固和对抗

前言 恶意软件为了不让我们很容易反编译一个apk,会对androidmanifest文件进行魔改加固,本文探索androidmanifest加固的常见手法以及对抗方法。这里提供一个恶意样本的androidmanifest.xml文件,我们学完之后可以动手实践。 1、Androidmanife…

加密经济学:Web3时代的新经济模型

随着Web3技术的迅猛发展,我们正迈入一个全新的数字经济时代。加密经济学作为这一时代的核心,不仅在数字货币领域崭露头角,更是重新定义了传统经济模型,为我们开启了一个充满创新和机遇的新纪元。 1. 去中心化的经济体系 Web3时代…

c++中的以及链表的基础使用

c中的& 通俗的立减即为对一个变量起别名。(是和指针有区别的) 以下为两个示例程序: 通过&代替了以往对地址的传递。从而实现了对a和b的交换。 p为a的别名,对p操作即为对a操作。故最后输出a的值为10. 链表的基础应用 链…

C语言:底层剖析——函数栈帧的创建和销毁

一、究竟什么是函数栈帧 C语言的使用是面向过程的, 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。所以C语言的程序都是以函数作为基本单位的,如果能够深入理解…

Vue项目 css下载字体并引入使用

1.下载字体 下载字体:字体下载,字体大全,免费字体下载,在线字体|字客网字客网是全球知名的字体下载与分享网站,齐全的中文,日文,韩文,英文,图标,美术设计,毛笔,钢笔,手写,书法字体大全,提供找字体,字体识别,字体下载,在线字体预览,字体转换,字体设计等服务。…

【idea】idea插件编写教程,博主原创idea插件 欢迎下载

前言:经常使用Objects.equals(a,b)方法的同学 应该或多或少都会因为粗心而传错参, 例如日常开发中 我们使用Objects.equals去比较 status(入参),statusEnum(枚举), 很容易忘记statusEnum.getCode() 或 statusEnum.getVaule() ,再比…

运筹说 第90期 | 网络计划-图解评审法

前述章节的网络计划方法主要研究以时间为主要参数的确定型网络模型,其中的概率型网络模型也只讨论工作公式的不确定性,并没有对事项或工作的不确定性进行讨论。由于这类网络模型的建立有严格的规则,大量研究与开发类计划尚无法表达。因从本期…

程序翻译过程详解

一、快速认识gcc和g gcc和g都是编译器,C语言可以用gcc或者是g来进行编译,但推荐使用gcc来进行编译。但C语言只能用g编译器来进行编译。 1.1语言和编译器的自举的过程 为了更好地认识gcc和g,在这里可以给大家介绍一下语言和编译器的自举的过程…

盘点那些好用的知识库软件,赶紧收藏起来

知识库软件,这个听起来有些书呆子味道的工具,实际上在企业运营中起着至关重要的作用。它就像公司的大脑,储存着我们的知识,并在我们需要时随时供应。下面,我要向你推荐五款好用的知识库软件,让你的信息管理…

开启C++之旅(下):引用、内联函数及现代特性(auto和范围for循环)

上次介绍了:开启C之旅(上):探索命名空间与函数特性(缺省参数和函数重载) 今天就接着进行c入门的知识讲解 文章目录 1.引用1.1引用概念1.2引用特性1.3常引用其他情况 1.4引用使用场景1.4.1做参数1.4.2做返回…

.net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别

//全局过滤器 builder.Services.AddMvc(m > { m.Filters.Add<AllResultFilter>(); }); 1、实现过滤器 public class AllResultFilter : IResultFilter {/// <summary>/// 结果执行后方法/// 不可更改结果/// </summary>/// <param name"con…

vue下载文件流效果demo(整理)

在 Vue 项目中&#xff0c;你可以使用 FileSaver.js 库来方便地下载文件流。FileSaver.js 封装了不同浏览器的下载方式&#xff0c;使得下载文件更加简单和兼容。以下是一个完整的示例方法&#xff1a; 首先&#xff0c;安装 FileSaver.js 库&#xff1a; <template>&l…

使用Go语言的HTTP客户端和服务器

使用Go语言进行HTTP客户端和服务器开发是一种高效且强大的方式。Go语言的标准库提供了对HTTP协议的全面支持&#xff0c;使得创建HTTP客户端和服务器变得简单。 首先&#xff0c;让我们来看一下如何创建一个简单的HTTP服务器。在Go中&#xff0c;可以使用net/http包来创建HTTP…

墙地砖外形检测的技术方案-图像分割

基础原理 由于对碗口进行缺口检测&#xff0c;因此只需要碗口的边界信息。得到陶瓷碗区域填充后的图像&#xff0c;对图像进行边缘检测。这是属于图像分割中的内容&#xff0c;在图像的边缘中&#xff0c;可以利用导数算子对数字图像求差分&#xff0c;将边缘提取出来。 案例…