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

设计模式探索:适配器模式

1. 适配器模式介绍

1.1 适配器模式介绍

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

适配器模式的主要作用是把原本不兼容的接口,通过适配修改做到统一,使得用户方便使用。比如,万能充电器和多接口数据线都是为了适配各种不同的接口。

在这里插入图片描述

为什么要转换接口?

  • 原接口和目标接口都已经存在,不易修改接口代码。
  • 抽象接口希望复用已有组件的逻辑。
1.2 适配器模式结构

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

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

适配器模式分为:

  • 类适配器

    在这里插入图片描述

  • 对象适配器

    在这里插入图片描述

两者的区别在于:适配器与适配者的关系。类适配器是继承关系,对象适配器是聚合关系。根据设计原则,聚合优先于继承,应多选用对象适配器。

1.3 代码示例
// 目标接口
public interface Target {void request();
}// 适配者类
public class Adaptee {public void specificRequest() {System.out.println("适配者中的业务代码被调用!");}
}// 类适配器
public class ClassAdapter extends Adaptee implements Target {@Overridepublic void request() {this.specificRequest();}
}// 对象适配器
public class ObjectAdapter implements Target {private Adaptee adaptee;public ObjectAdapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {this.adaptee.specificRequest();}
}// 测试代码
public class Client {public static void main(String[] args) {Target classAdapter = new ClassAdapter();classAdapter.request();Target objectAdapter = new ObjectAdapter(new Adaptee());objectAdapter.request();}
}

2. 适配器模式在实际开发中的应用

2.1 需求描述

为了提升系统的速度,将一些数据以 K-V 形式缓存在内存中,平台提供 get、put、remove 等 API 以及相关的管理机制。

功能实现的迭代过程,从 HashMap 到 Memcached 再到 Redis,要确保后面再增加新的缓存组件时,能够实现自由的切换,并且还要符合开闭原则。

在这里插入图片描述

设计问题:

  1. 如何在符合开闭原则前提下,实现功能的扩展?
  2. 两种客户端 API 不相同,如何保证自由切换?

使用适配器模式。

2.2 功能实现

使用适配器模式将功能相似的多种第三方组件(实现方案),统一成自己需要的 API,业务代码只依赖已经统一的 API,而不依赖第三方 API。

(1) 定义一个缓存接口,包含 get、put、remove 等操作方法。例如:

public interface Cache {void put(String key, Object value);Object get(String key);void remove(String key);
}

(2) 实现该接口的三个适配器,分别对应 HashMap、Memcached、Redis 三种缓存方案。例如:

// HashMap 适配器
public class HashMapCacheAdapter implements Cache {private Map<String, Object> cache = new HashMap<>();@Overridepublic void put(String key, Object value) {cache.put(key, value);}@Overridepublic Object get(String key) {return cache.get(key);}@Overridepublic void remove(String key) {cache.remove(key);}
}// Memcached 适配器
public class MemcachedCacheAdapter implements Cache {private MemcachedClient memcachedClient;public MemcachedCacheAdapter(MemcachedClient memcachedClient) {this.memcachedClient = memcachedClient;}@Overridepublic void put(String key, Object value) {memcachedClient.set(key, 0, value);}@Overridepublic Object get(String key) {return memcachedClient.get(key);}@Overridepublic void remove(String key) {memcachedClient.delete(key);}
}// Redis 适配器
public class RedisCacheAdapter implements Cache {private Jedis jedis;public RedisCacheAdapter(Jedis jedis) {this.jedis = jedis;}@Overridepublic void put(String key, Object value) {jedis.set(key, value.toString());}@Overridepublic Object get(String key) {return jedis.get(key);}@Overridepublic void remove(String key) {jedis.del(key);}
}

(3) 创建工厂类,根据配置文件中的配置来创建相应的缓存适配器。例如:

public class CacheAdapterFactory {public static Cache createCacheAdapter(String type) {if ("HashMap".equals(type)) {return new HashMapCacheAdapter();} else if ("Memcached".equals(type)) {MemCachedClient memCachedClient = new MemCachedClient();return new MemcachedCacheAdapter(memCachedClient);} else if ("Redis".equals(type)) {Jedis jedis = new Jedis("localhost", 6379);return new RedisCacheAdapter(jedis);} else {throw new IllegalArgumentException("Invalid cache type: " + type);}}
}

使用时,只需要调用工厂类的 createCacheAdapter 方法,传入缓存类型即可获取相应的缓存适配器。例如:

public class Client {public static void main(String[] args) {Cache cache = CacheAdapterFactory.createCacheAdapter("Redis");cache.put("key", "value");Object result = cache.get("key");cache.remove("key");}
}

3. 适配器模式总结

优点:

  1. 解耦合: 适配器模式允许两个没有直接关联的类协同工作,降低了它们之间的耦合度。
  2. 提高复用性: 通过适配器,可以重用现有的类,而不需要修改它们的代码。
  3. 统一接口: 适配器模式提供了一种方法来统一多个不同的接口,使得它们可以被统一对待。
  4. 隐藏实现: 适配器模式隐藏了现有类的实现细节,只暴露出需要的接口。
  5. 灵活性: 可以根据需要自由地适配不同的类,提供了高度的灵活性。

缺点:

  1. 单一适配限制: 使用类适配器时,一次最多只能适配一个适配者类,这可能限制了其应用范围。
  2. 系统复杂度: 如果过度使用适配器,可能会导致系统结构变得复杂,难以理解和维护。

适用场景:

  1. 接口统一: 当需要统一多个类的接口时,适配器模式可以有效地将它们适配到一个统一的接口。
  2. 兼容性需求: 当现有的接口无法修改,但需要与其他系统或模块兼容时,适配器模式可以提供解决方案。

相关文章:

设计模式探索:适配器模式

1. 适配器模式介绍 1.1 适配器模式介绍 适配器模式&#xff08;adapter pattern&#xff09;的原始定义是&#xff1a;将一个类的接口转换为客户期望的另一个接口&#xff0c;适配器可以让不兼容的两个类一起协同工作。 适配器模式的主要作用是把原本不兼容的接口&#xff0c…...

OpenCV 寻找棋盘格角点及绘制

目录 一、概念 二、代码 2.1实现步骤 2.2完整代码 三、实现效果 一、概念 寻找棋盘格角点&#xff08;Checkerboard Corners&#xff09;是计算机视觉中相机标定&#xff08;Camera Calibration&#xff09;过程的重要步骤。 OpenCV 提供了函数 cv2.findChessboardCorners…...

【深度学习】PyTorch深度学习笔记02-线性模型

1. 监督学习 2. 数据集的划分 3. 平均平方误差MSE 4. 线性模型Linear Model - y x * w 用穷举法确定线性模型的参数 import numpy as np import matplotlib.pyplot as pltx_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0]def forward(x):return x * wdef loss(x, y):y_pred…...

10.FreeRTOS_互斥量

互斥量概述 在博文“ FreeRTOS_信号量 ”中&#xff0c;使用了二进制信号量实现了互斥&#xff0c;保护了串口资源。博文链接如下&#xff1a; FreeRTOS_信号量-CSDN博客 但还是要引入互斥量的概念。互斥量与二进制信号量相比&#xff0c;能够多实现如下两个功能&#xff1a…...

EtherCAT总线冗余让制造更安全更可靠更智能

冗余定义 什么是总线冗余功能&#xff1f;我们都知道&#xff0c;EtherCAT现场总线具有灵活的拓扑结构&#xff0c;设备间支持线型、星型、树型的连接方式&#xff0c;其中线型结构简单、传输效率高&#xff0c;大多数的现场应用中也是使用这种连接方式&#xff0c;如下图所示…...

Android IdleHandler源码分析

文章目录 Android IdleHandler源码分析概述前提基本用法源码分析添加和删除任务执行任务 应用场景 Android IdleHandler源码分析 概述 IdleHandler是一个接口&#xff0c;它定义在MessageQueue类中&#xff0c;用于在主线程的消息队列空闲时执行一些轻量级的任务。IdleHandle…...

Mac安装stable diffusion 工具

文章目录 1.安装 Homebrew2.安装 stable diffusion webui 的依赖3.下载 stable diffusion webui 代码4.启动 stable diffusion webui 本体5.下载模型6.这里可能会遇到一个clip-vit-large-patch14报错 参考&#xff1a;https://brew.idayer.com/install/stable-diffusion-webui/…...

CVE-2024-6387Open SSH漏洞彻底解决举措(含踩坑内容)

一、漏洞名称 OpenSSH 远程代码执行漏洞(CVE-2024-6387) 二、漏洞概述 Open SSH是基于SSH协议的安全网络通信工具&#xff0c;广泛应用于远程服务器管理、加密文件传输、端口转发、远程控制等多个领域。近日被爆出存在一个远程代码执行漏洞&#xff0c;由于Open SSH服务器端…...

python的简单爬取

需要的第三方模块 requests winr打开命令行输入cmd 简单爬取的基本格式&#xff08;爬取百度logo为例&#xff09; import requests url"http://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" resprequests.get(url)#回应 #保存到本地 with open(&…...

【WEB前端2024】3D智体编程:乔布斯3D纪念馆-第60集-agent训练资讯APP重点推荐AI资讯内容(含视频)

【WEB前端2024】3D智体编程&#xff1a;乔布斯3D纪念馆-第60集-agent训练资讯APP重点推荐AI资讯内容&#xff08;含视频&#xff09; 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。d…...

【学术会议征稿】第三届智能电网与能源系统国际学术会议

第三届智能电网与能源系统国际学术会议 2024 3rd International Conference on Smart Grid and Energy Systems 第三届智能电网与能源系统国际学术会议&#xff08;SGES 2024&#xff09;将于2024年10月25日-27日在郑州召开。 智能电网可以优化能源布局&#xff0c;让现有能源…...

01. 课程简介

1. 课程简介 本课程的核心内容可以分为三个部分&#xff0c;分别是需要理解记忆的计算机底层基础&#xff0c;后端通用组件以及需要不断编码练习的数据结构和算法。 计算机底层基础可以包含计算机网络、操作系统、编译原理、计算机组成原理&#xff0c;后两者在面试中出现的频…...

iOS热门面试题(三)

面试题1&#xff1a;在iOS开发中&#xff0c;什么是MVC设计模式&#xff1f;请详细解释其各个组成部分&#xff0c;并给出一个实际应用场景&#xff0c;包括具体的代码实现。 答案&#xff1a; MVC设计模式是一种在软件开发中广泛使用的架构模式&#xff0c;特别是在iOS开发中…...

ECS中postTransform.Value = float4x4.Scale(1, math.sin(elapsedTime), 1)

在Unity的ECS&#xff08;Entity Component System&#xff09;架构中&#xff0c;postTransform.Value float4x4.Scale(1, math.sin(elapsedTime), 1); 用于设置一个变换矩阵的缩放部分。下面是对这行代码的详细解释&#xff1a; postTransform: 这是一个表示变换的组件或结构…...

VLM技术介绍

1、背景 视觉语言模型&#xff08;Visual Language Models&#xff09;是可以同时从图像和文本中学习以处理许多任务的模型&#xff0c;从视觉问答到图像字幕。 视觉识别&#xff08;如图像分类、物体保护和语义分割&#xff09;是计算机视觉研究中一个长期存在的难题&#xff…...

x264 编码器 AArch64 汇编函数模块关系分析

x264 编码器 AArch64 汇编介绍 x264 是一个流行的开源视频编码器,它实现了 H.264/MPEG-4 AVC 标准。x264 项目致力于提供一个高性能、高质量的编码器,支持多种平台和架构。对于 AArch64(即 64 位 ARM 架构),x264 编码器利用该架构的特性来优化编码过程。在 x264 编码器中,…...

windows10开启防火墙,增加入站规则后不生效,还是不能访问后端程序

一、背景&#xff1a; 公司护网要求开启防火墙&#xff0c;开启防火墙后&#xff0c;前后端分离的项目调试受影响&#xff0c;于是增加入站规则开放固定的后台服务端口&#xff0c;增加的mysql端口3306和redis端口6379&#xff0c;别人都可以访问&#xff0c;但是程序的端口808…...

academic-homepage:快速搭建个人学术主页,页面内容包括个人简介、教育经历、发布过的学术列表等,同时页面布局兼容移动端。

今天给大家分享GitHub 上一个开源的 GitHub Pages 模板 academic-homepage。 可帮助你快速搭建个人学术主页&#xff0c;页面内容包括个人简介、教育经历、发布过的学术列表等最基本内容&#xff0c;同时页面布局兼容移动端。 相关链接 github.com/luost26/academic-homepage …...

.env.development、.env.production、.env.staging

环境变量文件&#xff08;如 .env.development、.env.production、.env.staging&#xff09;用于根据不同的环境&#xff08;开发、生产、测试等&#xff09;配置应用程序的行为。 作用 .env.development&#xff1a;用于开发环境的配置。开发人员在本地开发时会使用这个文件…...

国密证书(gmssl)在Kylin Server V10下安装

1.查看操作系统信息 [root@localhost ~]# cat /etc/.kyinfo [dist] name=Kylin milestone=Server-V10-GFB-Release-ZF9_01-2204-Build03 arch=arm64 beta=False time=2023-01-09 11:04:36 dist_id=Kylin-Server-V10-GFB-Release-ZF9_01-2204-Build03-arm64-2023-01-09 11:04:…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...