适配器模式-不兼容结构的协调

news2024/11/25 7:08:54

 去英语国家旅游时,我们只会说中文,为了与当地人交流,我们需要购买个翻译器,将中文翻译成英文,而这运用了适配器模式。

1 概述

适配器模式(Adapter Pattern),将一个接口转换成客户喜欢的另一个接口,使接口不兼容的那些类可以一起工作。这里的接口指广义的接口,它可以表示一个方法或者一组方法的集合。适配器又称为包装器。

图 对象适配器模式

Target: 目标抽象类,定义客户所需接口。

Adapter:适配器类,可以调用另一个接口,作为一个适配器,对Adaptee和Target进行匹配。

Adaptee: 被适配者类,定义了一个已经存在的接口,这个接口需要适配。被适配者类一般是一个具体的类。

public class ChineseAdaptee {

    public void speakChinese(String content) {
        System.out.println(content);
    }

}

public interface EnglishTarget {

    void speakEnglish(String content);

}

public class EnglishToChineseAdapter implements EnglishTarget{

    private final ChineseAdaptee chineseAdaptee;

    public EnglishToChineseAdapter(ChineseAdaptee chineseAdaptee) {
        this.chineseAdaptee = chineseAdaptee;
    }

    @Override
    public void speakEnglish(String content) {
        if ("hello".equals(content)) {
            chineseAdaptee.speakChinese("你好");
        } else {
            chineseAdaptee.speakChinese("对不起,听不懂。");
        }
    }
}

public class Client {

    public static void main(String[] args) {
        ChineseAdaptee chineseAdaptee = new ChineseAdaptee();
        EnglishTarget englishTarget = new EnglishToChineseAdapter(chineseAdaptee);
        englishTarget.speakEnglish("hello");
        englishTarget.speakEnglish("nice to meet you");
//        运行结果:
//        你好
//        对不起,听不懂。
    }

}

1.1 类适配器模式

类适配器和对象适配器最大的区别在于其匹配器和适配者之间的关系是继承关系。

图 类适配器模式

由于Java语言不支持多重类继承,因此类适配器模式的使用受到了很多限制。

需求:老代码中有一个加密算法,把二进制数据使用md5算法加密,生成一个字符串。新需求中,要求对用户输入的“用户名+密码”字符串进行md5加密。

图 加密需求设计方案

public class Md5Adaptee {

    public String md5Encrypt(String str) {
        return "md5加密" + str;
    }

}

public interface UserInfoEncryptTarget {

    String encrypt(String username,String password);

}

public class UserInfoEncryptAdapter extends Md5Adaptee implements UserInfoEncryptTarget{
    @Override
    public String encrypt(String username, String password) {
        return md5Encrypt(username + password);
    }
}

public class Client {

    public static void main(String[] args) {
        UserInfoEncryptTarget userInfoEncryptTarget = new UserInfoEncryptAdapter();
        System.out.println(userInfoEncryptTarget.encrypt("admin","123456"));
    }

}

​​​​​​​1.2 缺省适配器模式(接口适配器)

当不需要实现一个接口所提供的方法时,可以先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现,那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求。

它适用于不想使用一个接口中的所有方法的情况。

图 接口适配器

ServiceInterface: 适配者接口,通常在该接口声名了大量的方法。

AbstractService: 缺省适配器类,使用空方法形式实现了在ServiceInterface接口中声名的方法。通常将它定义为抽象类,因为对它进行实例化没有任何意义。

ConcreteService: 具体业务类,继承了缺省适配器类,可以根据需要有选择性地覆盖在适配器类中定义的方法。

需求:有个文件流接口,定义了读文件、写文件及文件安全性验证三个方法。现在想定义一个类,用来验证文件安全性,而不想实现其他方法。

public interface FileInterface {

    void writeFile(String path, OutputStream outputStream);

    void readFile(String path);

    void verifyFile(String path);

}

public abstract class FileAbstract implements FileInterface{

    @Override
    public void writeFile(String path, OutputStream outputStream) {
        throw new RuntimeException("不能操作这个方法");
    }

    @Override
    public void readFile(String path) {
        throw new RuntimeException("不能操作这个方法");
    }

    @Override
    public void verifyFile(String path) {
        throw new RuntimeException("不能操作这个方法");
    }

}

public class VerifyFile extends FileAbstract{

    @Override
    public void verifyFile(String path) {
        System.out.println("安全性验证:" + path);
    }

}

public class Client {

    public static void main(String[] args) {
        FileInterface fileInterface = new VerifyFile();
        fileInterface.verifyFile("hello.java");
    }

}

适配器名称

实现

作用及优势

对象适配器

在适配类中关联一个被适配者对象,通过调用被适配者对象的方法来实现适配。

适配目标接口。扩展方便,可动态替换被适配者,来适配其他类。

类适配器

适配类继承被适配者类。

适配目标接口。使用继承方式,不方便扩展,但是实现方法比较方便。

接口适配器

通过一个抽象类来实现接口中的所有方法,具体类继承抽象类,根据需求重写特定的方法。

不想实现一个接口中的所有方法。

表 三种类型适配器模式对比

2 优缺点

优点:

  1. 将目标类和适配者类解耦,通过引入一个适配器来重用现有适配者类的功能,无须修改原有接口。
  2. 灵活性和扩展性很好,可以动态替换被替换者及适配器,符合开闭原则。
  3. 对于不想实现接口中所有方法的场景,适配器模式能按需求重写需要实现的方法。

缺点:

  1. Java不支持多重类继承,类适配器一次最多只能适配一个适配器。且目标抽象类只能为接口。有一定局限性。

3 适用场景

  1. 想适配老代码的相关接口。
  2. 不想实现接口中的所有方法。

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

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

相关文章

golang 日志库logrus和lumberjack 日志切割库实践

package mainimport (log "github.com/Sirupsen/logrus""gopkg.in/natefinch/lumberjack.v2" )func main() {logger : &lumberjack.Logger{// 日志输出文件路径Filename: "/var/log/myapp/foo.log",// 日志文件最大 size, 单位是 MBMaxSiz…

i.MX6Q应用处理器:MCIMX6Q5EYM12AD/MCIMX6Q5EYM10AE/MCIMX6Q5EYM10ADR 4核、32位,624-LFBGA

i.MX6Q 处理器代表了集成多媒体应用处理器的最新成就。这些处理器是不断增长的多媒体产品系列的一部分,这些产品提供高性能处理,并针对最低功耗进行了优化。 i.MX6Quad处理器采用先进的四核ArmCortex-A9内核,运行速度高达1.2 GHz。它们包括2…

什么?微信朋友圈能够一键转发了?

作为「国民级」聊天软件,微信朋友圈功能一直备受关注,毕竟社交 3 大巨头中,QQ 和微博都可以转发动态。那微信朋友圈能不能也像 QQ 空间这样,点击转发能分享到 QQ、微信和朋友圈呢? 那到底朋友圈转发怎么个转法&#xf…

前端Vue自定义弹框、自定义弹框内容 alertView showModel popup 组件

随着技术的发展,开发的复杂度也越来越高,传统开发方式将一个系统做成了整块应用,经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改,造成牵一发而动全身。 通过组件化开发,可以有效实现…

数据标注的类型有哪些?

构建像人类一样的AI或ML模型需要大量训练数据。要使模型做出决定并采取行动,就必须通过数据标注来训练模型,使其能够理解特定信息。 但是,什么是数据标注呢?数据标注是指对用于人工智能应用的数据进行分类和标注。我们必须针对特定…

SpringBoot教学篇------SpringBoot自动配置原理

一、SpringBoot自动配置的注解AutoWired SpringBoot的自动配置就是当Spring容器启动后,一些自动配置类(只是自动配置类,并不是当前的组件配置到IOC容器中,自动配置类通过Conditional注解来按需配置)就自动装配的IOC容…

微服务: 05-rabbitmq设置重试次数并设置死信队列

目录 1. 上文传送门: 2. 前言简介: 2.1 问: 消费端重复循环异常如何解决? 2.2 为什么要使用死信队列 2.3 案例思路 -> ps: 以下案例经过测试(思路一/二实现原理一样) -> 2.3.1 思路一 -> 2.3.2 思路二 3. 案例代码 3.1 简单介绍案例 3.2 声明交换机 队…

网络知识整合——Web页面请求的历程

Web页面请求的历程 内部涉及知识:一、准备:DHCP、UDP、IP 和以太网二、仍在准备:DNS和ARP三、仍在准备:域内路由选择到DNS服务器四、Web客户-服务器交互:TCP和HTTP五、HTTP请求响应格式Requests部分Responses 部分 下载一个Web页面…

【MySQL】_1.数据库基础

目录 1.数据库介绍 1.1 数据结构与数据库 1.2 常见的数据库软件 1.3 数据库的分类 1.4 MySQL介绍 1.4.1 重要概念 1.4.2 学习内容 1.4.3 数据库服务器在硬盘上组织数据的方式 2. 数据库操作 2.1 显示当前数据库 2.2 创建数据库 2.3 选中数据库 2.4 删除数据库 3…

在分区工具上,格式化分区和删除分区. 两者有什么不一样吗?

1.格式化分区:就是重建文件系统,等于把目标分区的数据全部清掉。 删除分区:你删除后可以再重新分区,可以分区多个分区,前提是“删除分区”的大小足够大。分了区,还必须格式化,才能用。 只有分了…

vue3+vite+pinia+vue-router搭建环境

前提:前面已经创建一个项目,涉及到vue3、vite、pinia、vue-router、openlayers创建的命令行及对应版本。接下来,是整个项目的详细配置。 详细配置,包括以下内容: 一、vue (一)、vue3,并且使用组合式API vue…

理解冯.诺依曼体系结构(操作系统和进程)

文章目录 一.冯诺依曼体系结构二.冯诺依曼体系结构与木桶效应三.操作系统与进程操作系统Linux系统中的进程 一.冯诺依曼体系结构 冯诺依曼体系结构特性: 冯诺依曼体系结构中的存储器指的是内存——一种硬件级别的缓存空间(介于IO设备与CPU之间,只有数据存储和读写功能,并且具有…

重排链表问题

给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。…

基础语言模型LLaMA

LLaMA包含从7B到65B参数的基础语言模型集合。Meta在数万亿个tokens上训练了模型,LLaMA-13B在大多数基准测试中优于GPT-3(175B)。 来自:LLaMA: Open and Efficient Foundation Language Models 目录 背景概述方法预训练数据架构Op…

会员管理系统如何深度绑定用户?会员系统必备哪些功能?

在以消费者为主导的企业(商家)范围内,实行会员制管理能够更好的提升客户的忠诚度,减少客户的流失。完整、精确的会员管理系统,更能提升企业(商家)的实际效益。 蚓链会员管理系统(专业版) 便是这…

VMware扩展磁盘提示:在部分链上无法执行所调用的函数。请打开父虚拟磁盘

VMware扩展磁盘提示:在部分链上无法执行所调用的函数。请打开父虚拟磁盘 在为VMware中的虚拟机扩展磁盘时提示:在部分链上无法执行所调用的函数。请打开父虚拟磁盘。 出现这个问题是因为你先前创建过快照,但是快照删除时候,残余文…

JAVA集成国密SM3

JAVA集成国密SM3加密、验签 一、pom配置二、加密代码集成2.1、目录结构2.2、源码2.3、测试 三、验签代码集成2.1、目录结构2.2、源码2.3、测试 四、相关链接 国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527 SM3杂凑算法 SM3 消息摘要。…

怎么学习Java数据库连接(JDBC)? - 易智编译EaseEditing

学习Java数据库连接(JDBC)是掌握Java与数据库交互的关键步骤。以下是学习Java JDBC的一些建议: 先掌握Java基础: 在学习JDBC之前,确保你已经掌握了Java的基本语法、面向对象编程和其他核心概念。这将有助于更好地理解…

干货分享:商城系统开发方式

商城系统是一种为了满足电子商务需求而开发的系统,它能够实现在线购物、支付、订单管理等功能。在当今互联网时代,商城系统的开发方式多种多样。那么,商城系统开发方式有哪些呢? 1、完全独立自主开发 完全独立自主开发是指企业根…

FactoryBean源码解析

文章目录 一、简介二、FactoryBean 接口的方法三、FactoryBean 与 BeanFactory 的区别四、源码解析五、实际应用 一、简介 FactoryBean 是 Spring 框架中的一个接口,用来创建特定类型的 Bean 对象。实现FactoryBean 接口就可以自定义 Bean 对象的创建过程。Factory…