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

前言

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

适配器模式

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

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

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

适配器模式有3个角色:

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

1 情景假设

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

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

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

2 代码示例

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

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

public interface GbaGame {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{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.mzph.cn/news/45626.shtml

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

相关文章

通过C实现sqlite3操作,(增删改查),导入电子词典

一、插入 #include <stdio.h> #include <sqlite3.h> void do_insert(sqlite3 *db); int main(int argc, const char *argv[]) {//创建并打开一个数据库sqlite3 *db NULL;if(sqlite3_open("./mysql.db",&db) ! SQLITE_OK){fprintf(stderr,"sql…

AUTOSAR配置与实践(配置篇)5.1 BSW的通信功能进阶

传送门 -> AUTOSAR配置与实践总目录 AUTOSAR配置与实践(配置篇)5.1 BSW的通信功能进阶 一、模块和收发流程主要配置项介绍1.1 模块介绍1.2 通知方式相关主要配置项二、收发流程详解2.1 发送流程2.2 发送确认过程2.2.1 发送确认过程(读数据方式:轮询)2.2.2 发送确认过程…

IDEA 如何制作代码补丁?IDEA 生成 patch 和使用 patch

什么是升级补丁&#xff1f; 比如你本地修复的 bug&#xff0c;需要把增量文件发给客户&#xff0c;很多场景下大家都需要手工整理修改的文件&#xff0c;并整理好目录&#xff0c;这个很麻烦。那有没有简单的技巧呢&#xff1f;看看 IDEA 生成 patch 和使用 patch 的使用。 介…

Centos升级openssl

依赖包 安装编译 OpenSSL 所需的包&#xff0c;包括 gcc、make、perl 和 zlib-devel。可以通过运行以下命令完成&#xff1a; yum install -y gcc make perl zlib-devel安装包下载 下载 OpenSSL 1.1.1 的源码包&#xff0c;可以从 OpenSSL 官网下载&#xff08;https://www.op…

一、Kafka概述

目录 1.3 Kafka的基础架构 1.3 Kafka的基础架构 Producer&#xff1a;消息生产者&#xff0c;就是向 Kafka broker 发消息的客户端Consumer&#xff1a;消息消费者&#xff0c;向 Kafka broker 取消息的客户端。Consumer Group&#xff08;CG&#xff09;&#xff1a;消费者组&…

使用pytorch 的Transformer进行中英文翻译训练

下面是一个使用torch.nn.Transformer进行序列到序列&#xff08;Sequence-to-Sequence&#xff09;的机器翻译任务的示例代码&#xff0c;包括数据加载、模型搭建和训练过程。 import torch import torch.nn as nn from torch.nn import Transformer from torch.utils.data im…

PyTorch学习笔记(十六)——利用GPU训练

一、方式一 网络模型、损失函数、数据&#xff08;包括输入、标注&#xff09; 找到以上三种变量&#xff0c;调用它们的.cuda()&#xff0c;再返回即可 if torch.cuda.is_available():mynn mynn.cuda() if torch.cuda.is_available():loss_function loss_function.cuda(…

SpringMVC之@RequestMapping注解

文章目录 前言一、RequestMapping介绍二、详解&#xff08;末尾附源码&#xff0c;自行测试&#xff09;1.RequestMapping注解的位置2.RequestMapping注解的value属性3.RequestMapping注解的method属性4.RequestMapping注解的params属性&#xff08;了解&#xff09;5.RequestM…

华为ENSP网络设备配置实战6(简单的链路聚合)

题目要求 1、创建聚合组&#xff0c;添加端口成员 2、PC1网段为vlan10&#xff0c;PC2网段为vlan20 3、LSW1为核心网关设备&#xff0c;正确配置PC网关 4、PC1与PC2互通 解题过程 1.1、 按照拓扑图&#xff0c;各个设备起名 sys &#xff08;进入系统视图&#xff09; sy…

写一个mysql 正则表达式,每三个img标签图片后面添加<hr>

你可以使用MySQL的REGEXP_REPLACE函数来实现这个需求。下面是一个示例的正则表达式和SQL语句&#xff1a; sql UPDATE your_table SET your_column REGEXP_REPLACE(your_column, (<img[^>]*>){3}, $0<hr>) WHERE your_column REGEXP (<img[^>]*>){3}…

TCP协议报文结构

TCP是什么 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的、全双工的传输协议。它使用头部&#xff08;Header&#xff09;和数据&#xff08;Data&#xff09;来组织数据包&#xff0c;确保数据的可靠传输和按序传递。 TCP协议报文结构 下面详细阐述TCP…

FRP内网穿透,配置本地电脑作为服务器

FRP内网穿透&#xff0c;配置本地电脑作为服务器 下载FRP服务端客户端 参考链接&#xff1a; https://www.it235.com/实用工具/内网穿透/pierce.html https://www.cnblogs.com/007sx/p/17469301.html 由于没有公网ip&#xff0c;所以尝试内网穿透将本地电脑作为服务器&#xff…

Servlet+JDBC实战开发书店项目讲解第11讲:管理员用户权限功能

ServletJDBC实战开发书店项目讲解第11讲&#xff1a;管理员用户权限功能 在这一讲中&#xff0c;我们将详细讲解如何实现书店项目中的管理员用户权限功能。下面是每个步骤的详细说明&#xff1a; 步骤一&#xff1a;创建管理员用户表 首先&#xff0c;我们需要在数据库中创建…

【Mariadb高可用MHA】

目录 一、概述 1.概念 2.组成 3.特点 4.工作原理 二、案例介绍 1.192.168.42.3 2.192.168.42.4 3.192.168.42.5 4.192.168.42.6 三、实际构建MHA 1.ssh免密登录 1.1 所有节点配置hosts 1.2 192.168.42.3 1.3 192.168.42.4 1.4 192.168.42.5 1.5 192.168.42.6 …

(二)结构型模式:7、享元模式(Flyweight Pattern)(C++实例)

目录 1、享元模式&#xff08;Flyweight Pattern&#xff09;含义 2、享元模式的UML图学习 3、享元模式的应用场景 4、享元模式的优缺点 5、C实现享元模式的简单实例 1、享元模式&#xff08;Flyweight Pattern&#xff09;含义 享元模式&#xff08;Flyweight&#xff09…

OpenCV笔记之solvePnP函数和calibrateCamera函数对比

OpenCV笔记之solvePnP函数和calibrateCamera函数对比 文章目录 OpenCV笔记之solvePnP函数和calibrateCamera函数对比1.cv::solvePnP2.cv::solvePnP函数的用途和工作原理3.cv::solvePnP背后的数学方程式4.cv::SOLVEPNP_ITERATIVE、cv::SOLVEPNP_EPNP、cv::SOLVEPNP_P3P5.一个固定…

C++ 自增自减运算符

自增运算符 会把操作数加 1&#xff0c;自减运算符 – 会把操作数减 1。因此&#xff1a; x x1;等同于x;同样的&#xff1a; x x-1;等同于x--;无论是自增运算符还是自减运算符&#xff0c;都可以放在操作数的前面&#xff08;前缀&#xff09;或后面&#xff08;后缀&…

【C++ STL之map,set,pair详解】

目录 一.map映射1.简介2.包含头文件及其初始化3.基本操作4.用迭代器正反遍历5.添加元素的四种方式6.元素的访问7.对比unordered_map&#xff0c;multimap 二.set集合1.简介2.包含头文件及其初始化3.基本操作4.元素的访问5.set&#xff0c;multiset&#xff0c;unordered_set&am…

为什么需要单元测试?

为什么需要单元测试&#xff1f; 从产品角度而言&#xff0c;常规的功能测试、系统测试都是站在产品局部或全局功能进行测试&#xff0c;能够很好地与用户的需要相结合&#xff0c;但是缺乏了对产品研发细节&#xff08;特别是代码细节的理解&#xff09;。 从测试人员角度而言…

Qt应用开发(基础篇)——纯文本编辑窗口 QPlainTextEdit

一、前言 QPlainTextEdit类继承于QAbstractScrollArea&#xff0c;QAbstractScrollArea继承于QFrame&#xff0c;是Qt用来显示和编辑纯文本的窗口。 滚屏区域基类https://blog.csdn.net/u014491932/article/details/132245486?spm1001.2014.3001.5501框架类QFramehttps://blo…