当前位置: 首页 > news >正文

设计模式学习之——适配器模式

适配器模式(Adapter Pattern),又称作变压器模式(因为这两者都体现了“转换”或“适配”的核心概念),是一种结构型设计模式。它将一个类的接口转换成客户端所期望的另一种接口,从而使得原本因接口不匹配而无法协同工作的两个类能够一起工作。

一、工作原理

适配器模式的工作原理是通过创建一个适配器类,该类包含一个源接口和一个目标接口。适配器类将客户端请求转换为源接口可以理解的命令,并执行相应的操作。这样,客户端只需要与适配器交互,而不需要直接与源接口交互,从而实现了接口的转换和适配。

二、主要角色

  • 目标接口(Target):定义客户端使用的接口,也就是客户端期望的接口。
  • 适配器(Adapter):实现目标接口,并持有一个源接口的引用,用于将客户端的请求转换成对源接口的调用。
  • 源接口(Adaptee):需要被适配的接口,即系统中已经存在的、但接口与目标接口不兼容的类。
  • 客户端(Client):使用目标接口来调用适配器的方法,从而间接调用源接口的方法。

三、实现方式

适配器模式有两种主要的实现方式:对象适配器和类适配器。

  • 对象适配器

    • 符合组合复用原则,使用了委托机制。
    • 在适配器类中维护一个被适配者(源接口)的成员变量,通过该成员变量调用被适配者的方法。
  • 类适配器

    • 通过类的继承关系实现适配器模式。
    • 适配器类继承被适配者类,通过super关键字调用被适配者的方法。

(注:在实际开发中,推荐使用对象适配器模式,因为组合通常比继承更加灵活,且更符合开闭原则。)

四、适用场景

  • 功能正确但接口不匹配:对于之前开发好的类,其操作和返回值都是正确的,但其定义的方法接口无法调用。此时可以使用适配器模式,使该类与用户的接口匹配,让用户使用适配器的接口,间接调用该类。
  • 软件维护阶段:在软件维护时,出现操作和返回值类似但函数接口不同的情况,为了适配第三方系统的接口,可以使用适配器模式。
  • 多个类的接口统一:当系统中的多个类的接口不统一时,可以使用适配器模式将它们的接口统一成一个接口,使这些类能够协同工作,提高系统的灵活性和可扩展性。

五、优缺点

  • 优点

    • 提高代码的复用性和灵活性:通过适配器模式,可以让原本不兼容的接口协同工作。
    • 降低耦合:目标类和现有类(被适配者)解除耦合,降低了系统的耦合性,易于扩展和维护。
    • 符合开闭原则:如果需要修改或扩展功能,只需要修改适配器类即可,目标类和现有类各自独立,互不影响。
  • 缺点

    • 增加代码的复杂度和维护成本:适配器模式需要增加一个额外的适配器类,增加了代码的量。如果设计不当,可能会导致适配器类的滥用,增加代码的混乱程度。
    • 降低可读性:系统代码可读性可能会降低,因为调用系统接口时,如果调用的是适配器接口,还需要查找调用的是哪个现有类的实际接口。

六、代码示例

示例一:电压适配器

假设我们有一个输出220V电压的设备(Voltage220V类),但我们有一个只能接受5V电压的设备(如手机,Phone类)。此时,我们可以使用适配器模式来创建一个电压适配器(VoltageAdapter类)。

// 被适配类:表示输出220V电压的设备
public class Voltage220V {public int output220V() {int src = 220;System.out.println("电压=" + src + "伏");return src;}
}// 适配接口:表示需要适配到的5V电压接口
public interface IVoltage5V {int output5V();
}// 适配器类:将220V电压适配为5V电压
public class VoltageAdapter implements IVoltage5V {private Voltage220V voltage220V;public VoltageAdapter(Voltage220V voltage220V) {this.voltage220V = voltage220V;}@Overridepublic int output5V() {int srcV = voltage220V.output220V(); // 获取220V电压int dstV = srcV / 44; // 转换为5V电压(这里仅为示例,实际转换可能更复杂)return dstV;}
}// 客户端类:表示只能接受5V电压的设备,如手机
public class Phone {// 充电方法,接受5V电压接口public void charging(IVoltage5V iVoltage5V) {if (iVoltage5V.output5V() == 5) {System.out.println("电压为5v,可以充电");} else if (iVoltage5V.output5V() > 5) {System.out.println("电压大于5v,无法充电");}}
}// 客户端测试代码
public class Client {public static void main(String[] args) {Phone phone = new Phone();Voltage220V voltage220V = new Voltage220V();VoltageAdapter voltageAdapter = new VoltageAdapter(voltage220V);phone.charging(voltageAdapter); // 通过适配器为手机充电}
}

在这个示例中,VoltageAdapter类作为适配器,将Voltage220V类的220V电压输出转换为5V电压输出,从而满足了Phone类的充电需求。

示例二:三相插座与两相插座的适配器

假设我们有一个三相插座(ThreeElectricOutlet接口)和一个两相插座(TwoElectricOutlet接口),以及一个只能插入两相插座的电视机(Tv类)。此时,我们可以使用适配器模式来创建一个三相到两相的插座适配器(TreeElecricAdapter类)。

// 三相插座接口
public interface ThreeElectricOutlet {void connectElectricCurrent();
}// 两相插座接口
public interface TwoElectricOutlet {void connectElectricCurrent();
}// 电视机类,实现了两相插座接口
public class Tv implements TwoElectricOutlet {private String name;public Tv() {name = "电视机";}public Tv(String name) {this.name = name;}@Overridepublic void connectElectricCurrent() {System.out.println(name + "开始播放节目");}
}// 三相到两相的插座适配器
public class TreeElecricAdapter implements ThreeElectricOutlet {TwoElectricOutlet outlet;public TreeElecricAdapter(TwoElectricOutlet teo) {this.outlet = teo;}@Overridepublic void connectElectricCurrent() {outlet.connectElectricCurrent();}
}// 客户端测试代码
public class TestActivity {public static void main(String[] args) {ThreeElectricOutlet outlet;Tv tv = new Tv("长虹电视机");TreeElecricAdapter adapter = new TreeElecricAdapter(tv);outlet = adapter;outlet.connectElectricCurrent(); // 通过适配器为电视机供电}
}

题外:适配器模式为什么又被称为变压器模式

适配器模式(Adapter Pattern)之所以又被称为变压器模式,是因为这两者都体现了“转换”或“适配”的核心概念。以下是对这一命名由来的详细解释:

1、功能上的相似性
  • 适配器模式

    • 主要解决的是接口不匹配的问题。
    • 通过适配器类,将一个类的接口转换成客户端所期望的另一种接口,从而使得原本因接口不匹配而不能一起工作的两个类能够一起工作。
  • 变压器

    • 在电力系统中,变压器的主要功能是将一种电压等级的电能转换成另一种电压等级的电能。
    • 通过变换电压,使得不同电压等级的电力系统能够相互连接和传输电能。

从功能上来看,适配器模式和变压器都起到了“转换”或“适配”的作用,使得原本不兼容的双方能够协同工作。

2、命名上的直观性
  • 适配器

    • 这个名称直接描述了该模式的主要功能,即适配或转换接口。
    • 在计算机领域中,适配器通常用于连接不同规格或类型的设备,使它们能够相互通信或协同工作。
  • 变压器

    • 这个名称同样直观地描述了其转换电压的功能。
    • 在电力系统中,变压器是不可或缺的转换设备。

将适配器模式命名为“变压器模式”,可以直观地反映出该模式在接口转换方面的作用,使得理解和记忆都更加方便。

综上所述,适配器模式是一种非常有用的设计模式,它能够在不修改现有类的基础上,实现接口的转换和适配,从而提高代码的复用性和灵活性。然而,在使用适配器模式时,也需要注意其可能带来的复杂度和维护成本问题。

相关文章:

设计模式学习之——适配器模式

适配器模式(Adapter Pattern),又称作变压器模式(因为这两者都体现了“转换”或“适配”的核心概念),是一种结构型设计模式。它将一个类的接口转换成客户端所期望的另一种接口,从而使得原本因接口…...

服务器数据恢复—热备盘上线过程中硬盘离线导致raid5阵列崩溃的数据恢复案例

服务器数据恢复环境: 两组分别由4块SAS接口硬盘组建的raid5阵列,两组raid5阵列划分LUN并由LVM管理,格式化为EXT3文件系统。 服务器故障: RAID5阵列中一块硬盘未知原因离线,热备盘自动激活上线替换离线硬盘。在热备盘上…...

MetaGPT源码 (Memory 类)

目录 MetaGPT源码:Memory 类例子 MetaGPT源码:Memory 类 这段代码定义了一个名为 Memory 的类,用于存储和管理消息(Message)对象。Memory 提供了多种操作消息的功能,包括添加单条或批量消息、按角色或内容筛选消息、删除最新消息…...

数据结构与算法复习AVL树插入过程

环境 $ cat /proc/version Linux version 6.8.0-45-generic (builddlcy02-amd64-115) (x86_64-linux-gnu-gcc-13 (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #45-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 30 12:02:04 UTC 2024 #include <std…...

小迪笔记第 五十天 文件包含漏洞 远程包含 本地包含 ctf练习题实战

前言 文件包含漏洞 原理就是包含的文件如果可控就会造成这个漏洞 php文件包含的特征 &#xff1a; PHP&#xff1a;include、require、include_once、require_once等 一共是分为了2 种 一个就是 远程文件包含 这个的前提是php开启了 远程文件上传这个选项 原理应用就是…...

单片机:实现点阵汉字平滑滚动显示(附带源码)

单片机实现点阵汉字平滑滚动显示 点阵显示技术是嵌入式系统中的常见显示技术之一&#xff0c;广泛应用于LED矩阵显示屏、广告牌、电子时钟等设备。在本项目中&#xff0c;我们将实现一个基于单片机的点阵汉字平滑滚动显示系统&#xff0c;使用LED点阵显示屏来实现动态滚动的汉…...

C# 实现 10 位纯数字随机数

本文将介绍如何用 C# 实现一个生成 10 位纯数字随机数的功能。以下是完整的代码示例&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace RandomTset {class Program{// 使用GUID作为种子来创建随机数生成器static…...

分布式全文检索引擎ElasticSearch-基本概念介绍

一、索引类型 索引&#xff0c;可以理解是我们的目录&#xff0c;看一本书的时候&#xff0c;可以根据目录准确快速定位到某一页&#xff0c;那么索引就可以帮我们快速定位到某条数据在庞大的数据表的哪一个位置。 我们常见的索引包括正排索引和倒排索引 1、正排索引 正排索…...

电子应用设计方案-49:智能拖把系统方案设计

智能拖把系统方案设计 一、引言 随着人们生活水平的提高和对清洁效率的追求&#xff0c;智能拖把作为一种创新的清洁工具应运而生。本方案旨在设计一款功能强大、操作便捷、清洁效果出色的智能拖把系统。 二、系统概述 1. 系统目标 - 实现自动清洁地面&#xff0c;减轻用户劳…...

汽车免拆诊断案例 | 2014款保时捷卡宴车发动机偶尔无法起动

故障现象 一辆2014款保时捷卡宴车&#xff0c;搭载3.0T 发动机&#xff0c;累计行驶里程约为18万km。车主反映&#xff0c;发动机偶尔无法起动。 故障诊断 接车后试车&#xff0c;发动机起动及运转均正常。用故障检测仪检测&#xff0c;发动机控制单元&#xff08;DME&#x…...

电脑怎么设置通电自动开机(工控机)

操作系统&#xff1a;win10 第一步&#xff0c;电脑开机时按del键进入bios页面。 第二步&#xff0c;选择advanced下的IT8712 Super IO Configuration 第三步&#xff0c;找到Auto Power On&#xff0c;将其从Power off设置为Power On 第四步&#xff0c;F10保存&#xff0c;大…...

MaxKB进阶:豆包大模型驱动的智能日报小助手

MaxKB进阶&#xff1a;豆包大模型驱动的智能日报小助手 说明&#xff1a; 在本教程中&#xff0c;我们通过“智能日报小助手”的应用场景&#xff0c;全面解析MaxKB的进阶功能&#xff1a;从如何接入公共大模型&#xff08;以豆包为例&#xff09;&#xff0c;到函数功能的灵活…...

Python爬虫之使用xpath进行HTML Document文档的解析

响应有两种&#xff1a;JSON数据和HTML页面&#xff0c;对于后者就需要进行解析HTML Documen得到我们需要的信息。 ① xpath使用 可以提前安装xpath插件&#xff0c;也可以自己从HTML源码解析。 &#xff08;1&#xff09;打开chrome浏览器 &#xff08;2&#xff09;点击右…...

调度系统:使用 Airflow 对 Couchbase 执行 SQL 调度时的潜在问题

使用 Airflow 对 Couchbase 执行 SQL 调度时&#xff0c;通常情况下不会直接遇到与 Couchbase 分布式特性相关的异常&#xff0c;但在某些特定情境下&#xff0c;可能会出现一些与分布式环境、调度和数据一致性相关的潜在问题。以下是一些可能会遇到的问题和建议的解决方案&…...

【数据结构——查找】二分查找(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;实现二分查找的算法。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.根据键盘输入的一组有序数据建立顺序表&#xff0c;2.顺序表的输…...

简单网页制作提升用户体验和客户转化

在当今竞争激烈的市场中&#xff0c;用户体验和客户转化率往往是决定企业成败的关键。简单而高效的网页制作&#xff0c;正是提升用户体验和客户转化的重要手段之一。 首先&#xff0c;简洁的网页设计能够有效减轻用户的认知负担。当用户打开一个层次分明、界面整洁的网站时&am…...

数据类型(使用与定义)

基本数据类型是CPU可以直接进行运算的类型&#xff0c;在算法直接被使用&#xff0c;主要包括&#xff1a; 整数类型&#xff1a;byte、short、int、long。 浮点数类型&#xff1a;float、double,用于表示小数。 字符类型&#xff1a;char&#xff0c;用于表示各种语言的字母…...

VMware:CentOS 7.* 连不上网络

1、修改网络适配 2、修改网卡配置参数 cd /etc/sysconfig/network-scripts/ vi ifcfg-e33# 修改 ONBOOTyes 3、重启网卡 service network restart 直接虚拟机中【ping 宿主机】&#xff0c;能PING通说明centOS和宿主机网络通了&#xff0c;只要宿主机有网&#xff0c;则 Ce…...

日志分析详解

文章目录 日志分析的概述日志分析的作用主要收集工具集中式日志系统主要特点采集日志分类ELK概述ELK收集日志的两种形式 搭建ELK平台安装部署docker添加镜像加速器安装部署Elasticsearch安装ElasticSearch-head&#xff08;可选&#xff09;运行容器页面无数据问题测试 安装Kib…...

【JavaWeb后端学习笔记】Maven项目管理

Maven 1、分模块设计2、Maven继承2.1 继承关系2.2 版本锁定 3、Maven聚合4、聚合与继承的关系 1、分模块设计 如果一个项目中含有大量的功能模块。可以考虑将这些功能分模块设计&#xff0c;逐一进行开发。例如将公共类可以定义在一个项目中&#xff0c;将通用工具类也放在一个…...

Docker--Docker Container(容器) 之 操作实例

容器的基本操作 容器的操作步骤其实很简单&#xff0c;根据拉取的镜像&#xff0c;进行启动&#xff0c;后可以查看容器&#xff0c;不用时停止容器&#xff0c;删除容器。 下面简单演示操作步骤 1.创建并运行容器 例如&#xff0c;创建一个名为"my-nginx"的交互…...

Android前端签到web迁移到rust的axum的过程-签到的重构

本次变更了以下内容: 为了使用之前ip2sta的ip到端点名的python,dic变量,将其存入redis hashset.使用地址/api/ip2dic 手动执行之.并且定义在/station/init,这个每天初始化redis的路径下.在rust axum的route中定义/sta/ip2dic,用来得到redis字典的内容,包含值和键.在前端的人名…...

用户认证系统登录界面

下面是使用HTML和JavaScript实现的一个中文版登录界面&#xff0c;包含登录、注册和修改密码功能。注册成功后会显示提示信息&#xff0c;在登录成功后进入一个大大的欢迎页面。 1.代码展示 <!DOCTYPE html> <html lang"zh-CN"> <head><meta …...

Redis从入门到进阶(总结)

以下内容均以CentOS7为背景。 一、Redis安装及启动 mysql&#xff08;读&#xff1a;2000/s&#xff1b;写&#xff1a;600/s&#xff09; redis&#xff08;读&#xff1a;10w/s&#xff1b;写&#xff1a;8w/s&#xff09;通过官方给出的数据单机并发可以达到10w/s&#xf…...

【D3.js in Action 3 精译_044】5.1 饼图和环形图的创建(四):数据标签的添加

当前内容所在位置&#xff1a; 第五章 饼图布局与堆叠布局 ✔️ 5.1 饼图和环形图的创建 ✔️ 5.1.1 准备阶段&#xff08;一&#xff09;5.1.2 饼图布局生成器&#xff08;二&#xff09;5.1.3 圆弧的绘制&#xff08;三&#xff09; ✔️5.1.4 数据标签的添加&#xff08;四&…...

Linux的基本功能和命令

Linux的基本功能和命令 切换目录 pwd 查询当前目录地址 cd /xxx/xxx 转到目录 cd …/ 回到上一级目录 cd ./ 当前目录 创建、删除文件/文件夹 创建文件\文件夹 touch filename 创建空文件mkdir 创建目录 mkdir -p 目标目录存在也不报错mkdir -p xxx/xxx 递归创建目录…...

【Spark】Spark的两种核心Shuffle工作原理详解

Spark 的shuffle机制 一、Spark ShuffleManager 发展历程 Spark 1.1.0 之前 在 Spark 1.1.0 之前&#xff0c;Spark 使用 BlockStoreShuffleFetcher 来处理 Shuffle 操作。这个实现主要依赖于直接从 BlockManager 获取 Shuffle 数据&#xff0c;并通过网络进行交换。 Spark …...

TCP 的文化内涵

从历史和文化内涵的视角看 TCP 协议的优势和局限&#xff0c;这些都刻在基因里。节约和经济获得向下兼容&#xff0c;但这也意味着它没有浪费带宽的本意&#xff0c;任何相左的优化策略终将遇到无法解决的困难&#xff0c;大致就这样&#xff0c;这为设计新协议提了意见&#x…...

ASP.NET |日常开发中读写XML详解

ASP.NET &#xff5c;日常开发中读写XML详解 前言一、XML 概述1.1 定义和结构1.2 应用场景 二、读取 XML 文件2.1 使用XmlDocument类&#xff08;DOM 方式&#xff09;2.2 使用XmlReader类&#xff08;流方式&#xff09; 三、写入 XML 文件3.1 使用XmlDocument类3.2 使用XmlWr…...

Less和SCSS,哪个更好用?

前言 Less 和 SCSS 都是流行的 CSS 预处理器&#xff0c;它们的目的都是扩展 CSS 的功能&#xff0c;使样式表更具组织性、可维护性和可重用性。虽然它们有许多相似之处&#xff0c;但在语法、特性和工作方式上也存在一些差异。 Less Less 是一种动态样式表语言&#xff0c;…...

wordpress读写分离配置/seo排名课程咨询电话

dst cv.distanceTransform(src, distanceType, maskSize[, dst[, dstType]]) 这个函数用来干嘛呢&#xff1f;&#xff1f;答&#xff1a;计算源图像中每个像素到最近零像素的距离。 参考&#xff1a;https://www.jianshu.com/p/fe4ec897dbf5 https://www.cnblogs.com/ssy…...

速度快的wordpress主机/正规网站优化哪个公司好

你知道如何在Excel中计算平方和吗&#xff1f;在Excel中查找平方和是一项重复的任务。最常用的公式需要大量数据输入。下面小编为你介绍一种简单好用的方法&#xff0c;让你可以快速计算平方和&#xff01;Microsoft Excel 2019 for Mac​www.macz.com查找多个单元的平方和在Ex…...

教育网站建设情况报告/产品品牌策划方案

问题你需要执行简单的时间转换&#xff0c;比如天到秒&#xff0c;小时到分钟等的转换。解决方案为了执行不同时间单位的转换和计算&#xff0c;请使用 datetime 模块。 比如&#xff0c;为了表示一个时间段&#xff0c;可以创建一个 timedelta 实例&#xff0c;就像下面这样&a…...

自己做的个人网站无法备案/如何做好平台推广

1234567891011121314151617181920212223# K近邻&#xff0c;适用于小型数据集&#xff0c;是很好的基准模型&#xff0c;容易解释from sklearn.neighbors import KNeighborsClassifier# 线性模型&#xff0c;非常可靠的首选算法&#xff0c;适用于很大的数据集&#xff0c;也适…...

杭州网站建设哪家好/手机系统优化软件哪个好

$secretKey 你的secretKey;$srcStr GETfaceid.tencentcloudapi.com/?;// 文档中示例是POST的 这里改成GET 这里踩个坑- -$param ["Action"> DetectAuth,//默认"Nonce"> rand(1000,9999),"SecretId">"你的secretId",Regio…...

济南网站推广¥做下拉去118cr/海外推广

vi /etc/sysconfig/syslog把SYSLOGD_OPTIONS"-m 0"修改为SYSLOGD_OPTIONS"-r -m 0" //-r 从远端主机写入 -m 0 sables MARK messagesvi /etc/syslog.conf加入下列内容把设备号为local4(PIX的默认设备号)的所有的日志记录到 /var/log/router.log中#Save pi…...