适配器模式详解和应用

目录

  • 适配器模式
    • 适配器模式结构
    • 适配器模式适用场景
    • 适配器模式优缺点
    • 练手题目
      • 题目描述
      • 输入描述
      • 输出描述
      • 题解

适配器模式

适配器模式是一种结构型设计模式, 它能使接口不兼容的对象能够相互合作。

适配器模式结构

对象适配器

实现时使用了构成原则: 适配器实现了其中一个对象的接口, 并对另一个对象进行封装。 所有流行的编程语言都可以实现适配器。

在这里插入图片描述

  1. 客户端 (Client) 是包含当前程序业务逻辑的类。

  2. 客户端接口 (Client Interface) 描述了其他类与客户端代码合作时必须遵循的协议。

  3. 服务 (Service) 中有一些功能类 (通常来自第三方或遗留系统)。 客户端与其接口不兼容, 因此无法直接调用其功能。

  4. 适配器 (Adapter) 是一个可以同时与客户端和服务交互的类: 它在实现客户端接口的同时封装了服务对象。 适配器接受客户端通过适配器接口发起的调用, 并将其转换为适用于被封装服务对象的调用。

  5. 客户端代码只需通过接口与适配器交互即可, 无需与具体的适配器类耦合。 因此, 你可以向程序中添加新类型的适配器而无需修改已有代码。 这在服务类的接口被更改或替换时很有用: 你无需修改客户端代码就可以创建新的适配器类。

对象适配器模式通用代码:

// 目标接口
interface Target {void request();
}// 被适配的类
class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}// 适配器类
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new Adapter(adaptee);target.request();}
}

类适配器

这一实现使用了继承机制: 适配器同时继承两个对象的接口。 请注意, 这种方式仅能在支持多重继承的编程语言中实现, 例如 C++。但是Java不支持多继承,所以使用Java时,对象适配器使用场景相对更多。

在这里插入图片描述

类适配器模式通用代码:

// 目标接口
interface Target {void request();
}// 被适配的类
class Adaptee {public void specificRequest() {System.out.println("Adaptee's specific request");}
}// 适配器类
class Adapter extends Adaptee implements Target {@Overridepublic void request() {specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Target target = new Adapter();target.request();}
}

类适配器与对象适配器的主要区别在于:

  1. 类适配器使用继承,而对象适配器使用组合。

  2. 类适配器可以重写Adaptee的方法,而对象适配器不能。

  3. 类适配器不需要额外的对象来进行适配,可能在某些情况下更高效。

  4. 类适配器只能适配一个类,而对象适配器可以适配多个类。

适配器模式适用场景

  1. 当你希望使用某个类, 但是其接口与其他代码不兼容时, 可以使用适配器类。

    适配器模式允许你创建一个中间层类, 其可作为代码与遗留类、 第三方类或提供怪异接口的类之间的转换器。

  2. 如果您需要复用这样一些类, 他们处于同一个继承体系, 并且他们又有了额外的一些共同的方法, 但是这些共同的方法不是所有在这一继承体系中的子类所具有的共性。

    你可以扩展每个子类, 将缺少的功能添加到新的子类中。 但是, 你必须在所有新子类中重复添加这些代码, 这样会使得代码有坏味道

    将缺失功能添加到一个适配器类中是一种优雅得多的解决方案。 然后你可以将缺少功能的对象封装在适配器中, 从而动态地获取所需功能。 如要这一点正常运作, 目标类必须要有通用接口, 适配器的成员变量应当遵循该通用接口。

在这里插入图片描述

识别方法: 适配器可以通过以不同抽象或接口类型实例为参数的构造函数来识别。 当适配器的任何方法被调用时, 它会将参数转换为合适的格式, 然后将调用定向到其封装对象中的一个或多个方法。

适配器模式优缺点

适配器模式优点:

  • 单一职责原则你可以将接口或数据转换代码从程序主要业务逻辑中分离。

  • 开闭原则。 只要客户端代码通过客户端接口与适配器进行交互, 你就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器。

适配器模式缺点:

  • 代码整体复杂度增加, 因为你需要新增一系列接口和类。 有时直接更改服务类使其与其他代码兼容会更简单。

练手题目

题目描述

小明购买了一台新电脑,该电脑使用 TypeC 接口,他已经有了一个USB接口的充电器和数据线,为了确保新电脑可以使用现有的USB接口充电器和数据线,他购买了一个TypeC到USB的扩展坞。

请你使用适配器模式设计并实现这个扩展坞系统,确保小明的新电脑既可以通过扩展坞使用现有的USB接口充电线和数据线,也可以使用TypeC接口充电。

输入描述

题目包含多行输入,第一行输入一个数字 N (1 < N <= 20),表示后面有N组测试数据。

之后N行都是一个整数,1表示使用电脑本身的TypeC接口,2表示使用扩展坞的USB接口充电。

输出描述

根据每行输入,输出相应的充电信息。

在这里插入图片描述

题解

类适配器模式代码:

import java.util.*;// 定义计算机端口接口
interface ComputerPort {void connect();
}// TypeC端口类实现ComputerPort接口
class TypeCPort implements ComputerPort {@Overridepublic void connect() {System.out.println("TypeC");}
}// USB设备类
class USBDevice {public void connectUSB() {System.out.println("USB Adapter");}
}// TypeC到USB适配器类
class TypeCToUSBAdapter extends USBDevice implements ComputerPort {@Overridepublic void connect() {super.connectUSB();}
}public class Main{public static void main(String[] args) {Scanner inputScanner = new Scanner(System.in);Map<Integer, ComputerPort> connectionModes = new HashMap<>();connectionModes.put(1, new TypeCPort());connectionModes.put(2, new TypeCToUSBAdapter());int totalConnections = inputScanner.nextInt();inputScanner.nextLine();while (inputScanner.hasNextInt()) {int choice = inputScanner.nextInt();connectionModes.getOrDefault(choice, () -> System.out.println("")).connect();}inputScanner.close();}
}

对象适配器模式:

import java.util.*;// 定义电脑端口接口
interface ComputerPort {void connect();
}// TypeC端口实现
class TypeCPort implements ComputerPort {@Overridepublic void connect() {System.out.println("TypeC");}
}// USB设备类
class USBDevice {public void connectUSB() {System.out.println("USB Adapter");}
}// TypeC到USB的扩展坞(适配器)
class TypeCToUSBHub implements ComputerPort {private USBDevice usbDevice;public TypeCToUSBHub(USBDevice usbDevice) {this.usbDevice = usbDevice;}@Overridepublic void connect() {usbDevice.connectUSB(); }
}public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 创建连接映射,用于存储不同类型的连接方式Map<Integer, ComputerPort> connections = new HashMap<>();connections.put(1, new TypeCPort());connections.put(2, new TypeCToUSBHub(new USBDevice()));scanner.nextInt(); scanner.nextLine(); while (scanner.hasNextInt()) {int choice = scanner.nextInt();ComputerPort connection = connections.get(choice);if (connection != null) {connection.connect();  } else {System.out.println("无效的选择"); }}scanner.close(); }
}

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

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

相关文章

重复图片查找:巧用Python和OpenCV进行图像哈希与汉明距离检测以从海量图片中找出重复图片

重复图片查找&#xff1a;巧用Python和OpenCV进行图像哈希与汉明距离检测以从海量图片中找出重复图片 1. 导言2. 环境准备3. 图像哈希&#xff08;pHash&#xff09;原理4. 汉明距离原理5. 代码实现导入必要的库图像哈希计算函数汉明距离计算函数查找重复图片函数示例使用 在处…

C++:内存管理(new,delete)

目录 C/C内存分布 C语言内存管理 C内存管理&#xff1a; new和delete的原理 new delete malloc/free和new/delete的区别 C/C内存分布 在C/C中&#xff0c;都有一块虚拟地址&#xff0c;内部井然有序的将代码分成了几部分&#xff0c;如下表&#xff1a; 栈&#xff1a;…

C++实现LRU缓存(新手入门详解)

LRU的概念 LRU&#xff08;Least Recently Used&#xff0c;最近最少使用&#xff09;是一种常用的缓存淘汰策略&#xff0c;主要目的是在缓存空间有限的情况下&#xff0c;优先淘汰那些最长时间没有被访问的数据项。LRU 策略的核心思想是&#xff1a; 缓存空间有限&#xff1…

深入浅出C语言指针(进阶篇)

深入浅出C语言指针(基础篇) 深入浅出C语言指针(进阶篇) 目录 引言 一、指针和数组 1.数组名的理解 2.指针访问数组 3.一维数组传参的本质 二、二级指针 1.二级指针的概念 2.二级指针的内存表示 3.二级指针的解引用 三、字符指针 1.指针指向单个字符 2.指针指向字…

【目标检测】Anaconda+PyTorch配置

前言 本文主要介绍在windows系统上的Anaconda、PyTorch关键步骤安装&#xff0c;为使用yolo所需的环境配置完善。同时也算是记录下我的配置流程&#xff0c;为以后用到的时候能笔记查阅。 Anaconda 软件安装 Anaconda官网&#xff1a;https://www.anaconda.com/ 另外&#…

Golang | Leetcode Golang题解之第278题第一个错误的版本

题目&#xff1a; 题解&#xff1a; func firstBadVersion(n int) int {return sort.Search(n, func(version int) bool { return isBadVersion(version) }) }

Elasticsearch基础(六):使用Kibana Lens进行数据可视化

文章目录 使用Kibana Lens进行数据可视化 一、进入Kibana Lens 二、基础可视化 1、指标可视化 2、垂直堆积条形图 3、表格 三、高级可视化 1、多图层和索引 2、子桶 3、树状图 使用Kibana Lens进行数据可视化 一、进入Kibana Lens 在Kibana主页&#xff0c;单击页面…

vxe-table——实现切换页码时排序状态的回显问题(ant-design+elementUi中table排序不同时回显的bug)——js技能提升

之前写的后台管理系统&#xff0c;都是用的antdelement&#xff0c;table组件中的【排序】问题是有一定的缺陷的。 想要实现的效果&#xff1a; antv——table组件一次只支持一个参数的排序 如下图&#xff1a; 就算是可以自行将排序字段拼接到列表接口的入参中&#xff0c…

Druid【基础 01】是什么+主要特点+设计原则+架构+数据结构(简单入门Druid)

Druid入门 1. 是什么2. 主要特点3. 三个设计原则4. Architecture 架构5. 数据结构5.1 DataSource 结构5.2 Segment 结构 Druid 非中文官网&#xff0c;内容不少且介绍的挺详细的&#xff0c;需要英文阅读能力或者翻译工具进行辅助。 1. 是什么 先看看官网怎么说&#xff1a; A…

请你谈谈:spring bean的生命周期 - 阶段5:BeanPostProcessor前置处理-自定义初始化逻辑-BeanPostProcess后置处理

BeanPostProcessor的postProcessBeforeInitialization方法是在bean的依赖注入&#xff08;即属性填充&#xff09;完成后&#xff0c;但在bean的初始化回调&#xff08;如PostConstruct注解的方法或InitializingBean接口的afterPropertiesSet方法&#xff09;之前被调用的。 具…

证书上的服务器名错误解决方法

方法 win r &#xff0c;输入mmc 点击文件——>添加/删除管理单元 找到证书——> 添加 根据自己的存放选择存放位置 点击控制台根节点——> 受信任的根证书颁发机构——>导入 若还出现问题&#xff0c;则参考https://blog.csdn.net/mm120138687/article/details/…

立创梁山派--移植开源的SFUD万能的串行 Flash 通用驱动库

SFUD是什么 关于SFUD库的介绍&#xff0c;其开源链接(gitee,github)已经详细的阐述了. 这里是截取自它的一部分介绍&#xff1a; SFUD 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多&#xff0c;各个 Flash 的规格及命令存在差异&#xff0c; SF…

Apache Tomcat文件包含漏洞复现(详细教程)

1.漏洞原理 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;其安装后会默认开启ajp连接器&#xff0c;方便与其他web服务器通过ajp协议进行交互。属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和…

【接口自动化_07课_Pytest+Excel+Allure完整框架集成_下】

目标&#xff1a;优化框架场景 1. 生成对应的接口关联【重点】 2. 优化URL基础路径封装【理解】 3. 利用PySQL操作数据库应用【理解】--- 怎么用python连接数据库、mysql 4. 通过数据库进行数据库断言【重点】 5. 通过数据库进行关联操作【重点】 一、接口关联&#xff1a…

MSP430M03507最小系统板的keil环境搭配,用keil编辑ti单片机

转载自嘉立创MSP430M03507开发手册 这篇文章只是因为我的keil版本与嘉立创的不一样&#xff0c;所以添加了我自己遇到的问题解析 先说说为什么要用keil编辑&#xff0c;因为ti单片机自己的ccs编译环境需要对应仿真器&#xff0c;那个加芯片都240了&#xff0c;哪有那么多钱买…

node.js中nodemon : 无法加载和使用问题,这是由于windows安全策略影起的按如下操作即可

1、用管理员权限打开vscode 2、文件终端中打开&#xff0c;输入 Set-ExecutionPolicy -Scope CurrentUser 3、再输入RemoteSigned 4、使用get-ExecutionPolicy查看权限&#xff0c;可以看到变为了RemoteSigned 重启问题解决

MySQL面试索引篇

1、什么是索引&#xff1f; 作为一个数据库&#xff0c;首要任务就是把数据存储好&#xff0c;并快速查询出用户需要的数据&#xff0c;而索引就相当于图书的目录一样&#xff0c;是一种用于快速查询和检索数据的数据结构&#xff0c;其本质可以看成是一种排序好的数据结构。 …

TypeScript 教程(九):类型声明文件与异步编程

目录 前言回顾装饰器与高级类型操控1. 类型声明文件a. 什么是类型声明文件&#xff08;.d.ts&#xff09;b. 编写和使用类型声明文件 2. 异步编程a. Promise 类型b. async/awaitc. 异步迭代器 3. 并行执行与错误处理a. Promise.allb. Promise.racec. 错误处理 结语 前言 在前几…

华为云.云日志服务LTS及其基本使用

云计算 云日志服务LTS及其基本使用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550…

数学建模(7)——Logistic模型

一、马尔萨斯人口模型 import numpy as np import matplotlib.pyplot as plt# 初始人口 N0 100 # 人口增长率 r 0.02 # 时间段&#xff08;年&#xff09; t np.linspace(0, 200, 200)# 马尔萨斯人口模型 N N0 * np.exp(r * t)# 绘图 plt.plot(t, N, labelPopulation) plt.…