学习设计模式之适配器模式,但是宝可梦

前言

作者在准备秋招中,学习设计模式,做点小笔记,用宝可梦为场景举例,有错误欢迎指出。

适配器模式

意图:将一个类的接口转换成客户希望的另一个接口

主要解决:把现有对象放到新环境里,而新环境要求的接口,现有对象不满足

何时使用:现有的类被需要,而这个类的接口不符合要求;建立一个可复用的类,用于让彼此之间无关的类或未来可能引入的类可以一起工作

适配器模式有3个角色:

  • 目标接口 (Target):当前系统业务期待的接口
  • 适配者类:被适配的现有组件的接口
  • 适配器类:一个转换器,继承或引用适配者对象,把适配者接口转为目标接口

1 情景假设

现在我们假设这样一个场景:小智在绿宝石的存档中,有一只巨tm强的裂空座,性格好,个体高,努力值也刷得完美。现在已经发售了朱紫,他还想用这只裂空座,但是问题来了,绿宝石是GBA主机的游戏,朱紫是Switch主机的游戏,他们存储数据的格式不同啊!这怎么办呢?那么就只能推出一个适配器,把GBA的数据转化成Switch的数据,把裂空座从绿宝石移植到朱紫,可能熟悉宝可梦游戏的朋友已经想到了,Pokemon Home就是干这个事的,所以我们可以把这个故事中的角色抽象为适配器模式需要的三个角色:

  • 目标接口:Switch数据
  • 适配者类:GBA数据
  • 适配器类:Pokemon Home

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XgCLolGk-1692546675681)(D:\笔记笔记笔记\设计模式.assets\image-20230820232858251.png)]

2 代码示例

在这里插入图片描述

首先定义个顶层接口:

public interface Game {
}

现有的接口,就是老版本GBA游戏:

public interface GbaGame extends Game{void usePokemon(String dataFormat);
}public class EmeraldVersion implements GbaGame{/*** 在绿宝石中使用宝可梦*/public void usePokemon(String dataFormat, String version) {System.out.println("Go! Rayquaza! (In " + version + " Version)");}public void usePokemon() {System.out.println("Go! Rayquaza! (In GBA Version )");}
}

有绿宝石一个实现类,然而,现在游戏已经到了朱紫版本,需要的是Switch上的数据:

public interface NsGame extends Game{void usePokemon(String dataFormat);
}public class ScarletVersion implements NsGame{public void usePokemon(String dataFormat){if ("nsData".equals(dataFormat)){// 内置功能,使用当前版本的宝可梦System.out.println("Go! Chikorita (Get In Scarlet Version)");}}
}

于是为了让NS端适配GBA的数据,我们需要一个适配器,这个适配器要有旧版本的属性(因为适配器是为已有的类设计的)

/*** Pokemon Home*/
public class DataAdapter implements GbaGame{GbaGame gbaGame; // 旧世代public DataAdapter(GbaGame gbaGame) {this.gbaGame = gbaGame;}@Overridepublic void usePokemon(String dataFormat) {if("gbaData".equals(dataFormat)){gbaGame.usePokemon(dataFormat);}}
}

所以,要在新版本(NsGame)中使用旧版本的数据,新版本应该是:

public class ScarletVersion implements NsGame{DataAdapter dataAdapter;public void usePokemon(String dataFormat){if ("gbaData".equals(dataFormat)){dataAdapter = new DataAdapter(new EmeraldVersion());dataAdapter.usePokemon(dataFormat, "Switch");}else if ("nsData".equals(dataFormat)){// 内置功能,使用当前版本的宝可梦System.out.println("Go! Chikorita (Get In Scarlet Version)");}}
}

注意:这里并不违背“开闭原则”,因为前面的ScarletVersion类只是为了说明逻辑,并不是对代码进行修改

测试类

public class AdapterDemo {public static void main(String[] args) {// 老版本使用EmeraldVersion emeraldVersion = new EmeraldVersion();emeraldVersion.usePokemon();// 新版本使用NsGame pokemon = new ScarletVersion();pokemon.usePokemon("gbaData");pokemon.usePokemon("nsData");}
}
Go! Rayquaza! (In GBA Version )
Go! Rayquaza! (In Switch Version)
Go! Chikorita (Get In Scarlet Version)

3 扩展

有聪明的读者就会问了:那既然有开闭原则,那如果有新的旧版本或者新版本要加入怎么办呢?

  • 旧版本增加:比如我想把3DS上的宝可梦拿到朱紫用,要怎么办?

如果无视开闭原则,可以这样修改,但其实这种情况更适用于,一开始就告诉了开发者,要适配2个旧版本。

public class DataAdapter implements GbaGame, ThreeDS{GbaGame gbaGame; // 旧世代ThreeDS threeDS; // 3DS世代游戏public DataAdapter(GbaGame gbaGame, ThreeDS threeDS) {this.gbaGame = gbaGame;this.threeDS = threeDS;}@Overridepublic void usePokemon(String dataFormat, String newVersion) {if("gbaData".equals(dataFormat)){gbaGame.usePokemon(dataFormat, newVersion);}else if("threeDS".equals(dataFormat)){threeDS.usePokemon(dataFormat, newVersion);}}
}

所以正确的做法是:为ThreeDS单独再写一个适配器类

public ThreeDsAdapter implements ThreeDS{//...
}
  • 目标接口的新实现:比如剑盾版本也是NS端的,和朱紫写一样的逻辑即可

3 另一个例子

题外话,在学习这个设计模式的时候想到的,在做机器学习的时候,通常有这么个流程:

数据集 -> 数据源 -> 模型 -> …

数据集的格式各不相同,然而,模型的输入是固定的,我们把数据集转换成能够进入模型的过程通常被叫做数据预处理,这是为了让数据集和模型输入的格式适配。比如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jOAlRVL1-1692546675682)(D:\笔记笔记笔记\设计模式.assets\image-20230820234746268.png)]

每个数据集的分割符不同,那么为了提供给模型一个模型能够接受的格式,就可以使用适配器模式,让数据从csv或者dat格式转换为data_df,即dataframe对象的过程,也就是适配的过程。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爱校对如何帮助企业和博客主提高在线可见性?

在数字化时代,内容质量已经成为增强在线曝光率的关键因素。企业和博客主经常面临挑战,如何制作高质量、无误的内容以吸引更多的在线用户。此文将详细分析“爱校对”如何帮助用户优化内容,从而提高在线可见性。 1.互联网内容的挑战 搜索引擎…

ClickHouse(二十三):Java Spark读写ClickHouse API

进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容! 🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…

Vue3组合式API详解 - 大型应用的高端写法

目录 01-setup方法与script_setup及ref响应式02-事件方法_计算属性_reactive_toRefs03-生命周期_watch_watchEffect04-跨组件通信方案provide_inject05-复用组件功能之use函数06-利用defineProps与defineEmits进行组件通信 01-setup方法与script_setup及ref响应式 在Vue3.1版本…

玩转单元测试之gtest

引言 程序开发的时候,往往需要编写一些测试样例来完成功能测试,以保证自己的代码在功能上符合预期,能考虑到一些异常边界问题等等。 gtest快速入门 1.引入gtest # 使用的是1.10版本,其他版本可根据需要选择 git clone -b v1.1…

基于图卷积网络的知识嵌入8.21

基于图卷积网络的知识嵌入 摘要介绍 摘要 近年来,围绕图卷积网络(GCN)这一主题出现了大量的文献。如何有效地利用复杂图中丰富的结构信息(例如具有heterogeneous types of entities and relations(异构实体和关系类型) 的知识图谱…

API 接口选择那个?RESTful、GraphQL、gRPC、WebSocket、Webhook

大家好,我是比特桃。目前我们的生活紧紧地被大量互联网服务所包围,互联网上每天都有数百亿次API调用。API 是两个设备相互通讯的一种方式,人们在手机上每次指尖的悦动,背后都是 API 接口的调用。 本文将列举常见的一些 API 接口&…

element-ui中二次封装一个带select的form组件

带select的form组件 样式 代码 <template><el-form-item label"是否有" class"append" prop"tag"><el-form-itemprop"isShare"><el-select v-model"query.tag"><el-option v-for"(item, …

2023国赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

4.物联网LWIP之C/S编程,实现服务器大小写转换

LWIP配置 服务器端实现 客户端实现 错误分析 一。LWIP配置&#xff08;FREERTOS配置&#xff0c;ETH配置&#xff0c;LWIP配置&#xff09; 1.FREERTOS配置 为什么要修改定时源为Tim1&#xff1f;不用systick&#xff1f; 原因&#xff1a;HAL库与FREERTOS都需要使用systi…

错题整理——测开2021网易

1. 某些bug不影响使用时&#xff0c;可以选择先上线&#xff0c;在维护过程中修复。 2. df&#xff1a;查看磁盘使用情况 dir不是linux的常用的命令&#xff0c;不过用dir能够罗列出目录内容&#xff1b;dir默认没有颜色的区别&#xff0c;但也可以设置。现在都使用ls来代替。…

微信小程序卡片横向滚动竖图

滚动并不是使用swiper&#xff0c;该方式使用的是scroll-view实现 Swiper局限性太多了&#xff0c;对竖图并不合适 从左往右滚动图片示例 wxml代码&#xff1a; <view class"img-x" style"margin-top: 10px;"><view style"margin: 20rpx;…

三种生成树(STP,RSTP,MSTP)的基本配置(自我理解)

目录 一、为什么要使用生成树&#xff08;STP)&#xff1a; 二、由于设备冗余而导致的问题&#xff1a; 广播风暴&#xff1a; 三、802.1D生成树基本配置 四、802.1D生成树实验 实验拓扑&#xff1a; 实验配置&#xff1a; 配置完成后&#xff0c;在SW8上观察现象&…

RedisDesktopManager 连接redis

redis查看是否启动成功 ps -ef | grep redis以上未启动成功 cd /usr/local/bin/ 切换根目录 sudo -i 开启服务端 ./redis-server /usr/local/redis/redis.conf 开启客户端 ./redis-cli

JUC--阻塞队列

目录 问题引出 一.单端阻塞队列&#xff08;BlockingQueue&#xff09; 二.双端阻塞队列&#xff08;BlockingDeque&#xff09; 三.延迟队列&#xff08;DelayQueue&#xff09; 问题引出 由于实现消费者-生产者模型&#xff0c;每一次实现都比较麻烦&#xff0c;比如sych…

Python批量爬虫下载文件——把Excel中的超链接快速变成网址

本文的背景是&#xff1a;大学关系很好的老师问我能不能把Excel中1000个超链接网址对应的pdf文档下载下来。虽然可以手动一个一个点击下载&#xff0c;但是这样太费人力和时间了。我想起了之前的爬虫经验&#xff0c;给老师分析了一下可行性&#xff0c;就动手实践了。    没…

4.SpringCloud 基本架构

1.SpringCloud概述 Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具&#xff08;例如配置管理&#xff0c;服务发现&#xff0c;断路器&#xff0c;智能路由&#xff0c;微代理&#xff0c;控制总线&#xff0c;一次性令牌&#xff0c;全局锁&#xff0c;…

测试框架pytest教程(2)-用例依赖库-pytest-dependency

对于 pytest 的用例依赖管理&#xff0c;可以使用 pytest-dependency 插件。该插件提供了更多的依赖管理功能&#xff0c;使你能够更灵活地定义和控制测试用例之间的依赖关系。 Using pytest-dependency — pytest-dependency 0.5.1 documentation 安装 pytest-dependency 插…

【源码篇】ThreadLocal源码解析(主打的就是通俗易懂,言简意赅)

文章目录 ThreadLocal学习笔记前言1、TheadLocal基本介绍2、ThreadLocal基本使用3、体验ThreadLocal的优点3.1 ThreadLocal与synchronized的比较3.2、ThreadLoca的应用场景 4、ThreadLocal的内部原理4.1 ThreadLocal内部结构4.2 ThreadLocal常用方法分析4.2.1 set原理分析4.2.2…

云计算在IT领域的发展和应用

文章目录 云计算的发展历程云计算的核心概念云计算在IT领域的应用1. 基础设施即服务&#xff08;IaaS&#xff09;&#xff1a;2. 平台即服务&#xff08;PaaS&#xff09;&#xff1a;3. 软件即服务&#xff08;SaaS&#xff09;&#xff1a; 云计算的拓展应用结论 &#x1f3…

学习maven工具

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f3e8;maven工具产生的背景&#x1f993;maven简介&#x1fa80;pom.xml文件(project object Model 项目对象模型) &#x1fa82;maven工具安装步骤两个前提&#xff1a;下载 m…