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

news2024/12/23 17:59:13

前言

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

适配器模式

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

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

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

适配器模式有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;
    }

    @Override
    public 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;
    }

    @Override
    public 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.coloradmin.cn/o/905076.html

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

相关文章

leetcode几个数组题

数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合 因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址 二分查找 移除元素 有序数组的平方 209.长度最小的子数组

设计模式——开闭原则

文章目录 基本介绍看下面一段代码方式 1 的优缺点改进的思路分析 基本介绍 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽…

wustoj2008折扣

#include <stdio.h> int main() {int n,m;double c;scanf("%d%d",&n,&m);cn*(m/10.00);printf("%.2lf",c);return 0;}

茂名 湛江阳江某学校 ibm x3850服务器维修经历

简介&#xff1a;中国广东省阳江市某中学联想 IBM System x3850 x6服务器维修 io板故障处理经历分享&#xff1a; 这一天一位阳江的老师经其他学校老师介绍推荐对接我&#xff0c;说他们学校有一台ibm服务器出问题了&#xff0c;老师大致跟我描述了一下这台服务器发生故障的前…

3、Spring之底层架构核心概念解析

BeanDefinition BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点。比如: class,表示Bean类型scope,表示Bean作用域,单例或原型等lazyInit:表示Bean是否是懒加载initMethodName:表示Bean初始化时要执行的方法destroyMethodName:表示Be…

【算法刷题之数组篇(1)】

目录 1.leetcode-59. 螺旋矩阵 II&#xff08;题2.题3相当于二分变形&#xff09;2.leetcode-33. 搜索旋转排序数组3.leetcode-81. 搜索旋转排序数组 II(与题目2对比理解)&#xff08;题4和题5都是排序双指针&#xff09;4.leetcode-15. 三数之和5.leetcode-18. 四数之和6.leet…

Python制作爱心并打包成手机端可执行文件

前言 本文是想要将python代码打包成在手机上能执行的文件 尝试了几个库&#xff0c; 有这也那样的限制&#xff0c;最终还是选了BeeWare 环境&#xff1a;python3.7.x 开始 找到打包有相关工具os-android-apk-builder&#xff0c;buildozer&#xff0c;cx_Freeze&#xff…

AMBA总线协议(1)——概述

目录 一、AMBA总线简介 二、基于AMBA 的典型微控制器 三、AHB介绍 1、概述 2、典型结构 &#xff08;1&#xff09; AHB 主机&#xff08;AHB Master&#xff09; &#xff08;2&#xff09;AHB 从机&#xff08;AHB Slave&#xff09; &#xff08;3&#xff09;AHB 仲裁…

基础论文学习(1)——ViT

https://zhuanlan.zhihu.com/p/308301901 1 图片分块和降维 因为transformer encoder的输入需要序列&#xff0c;所以最简单做法就是把图片切分为patch&#xff0c;然后拉成序列即可。 假设输入图片大小是256x256&#xff0c;打算分成64个patch&#xff0c;每个patch是32x32…

[MySQL]02关于事务的解析

目录 原子性 一致性 持久性 隔离性 事务隔离级别 并发执行可能存在问题 脏读问题 不可重复读 幻读 难点解析 原子性 事务最核心的就是原子性 以前人们认为原子不可再分&#xff0c;用原子性来表示一个事务不可分割 update account set balancebalance-500 where nam…

Go语言入门指南:基础语法和常用特性(下)

上一节&#xff0c;我们了解Go语言特性以及第一个Go语言程序——Hello World&#xff0c;这一节就让我们更深入的了解一下Go语言的**基础语法**吧&#xff01; 一、行分隔符 在 Go 程序中&#xff0c;一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号 ;…

MySQL基础篇(二)

DML 定义&#xff1a;Data Manipulation Language、数据操作语言&#xff08;增删改&#xff09; 添加数据&#xff08;INSERT&#xff09;修改数据&#xff08;UPDATE&#xff09;删除数据&#xff08;DELETE&#xff09; 添加数据&#xff08;INSERT&#xff09; 给指定的…

day0818

1. #include <myhead.h> int file_len(const char*strfile, const char*dstfile); void file_copy(const char* strfile, const char* dstfile, int start, int size); int main(int argc, const char *argv[]) {//判断是否传入两个文件if(argc!3){printf("input fi…

最新消息:谷歌将在Chromebook上运用UWB技术,无线通信更上一层

超宽带&#xff08;UWB&#xff09;技术是一种创新的短距离无线通信技术&#xff0c;具有高速数据传输和精确定位物体位置的优势。尽管该技术已经存在一段时间&#xff0c;但最近开始广泛应用于各种设备中。据最新报道&#xff0c;Pixel Watch 2可能会搭载UWB模块&#xff0c;这…

VSCode之C++ SQLite3 SmartDB实现

背景 承接上篇VSCode配置之C & SQLite3极简配置方案&#xff0c;参考《深入应用C11: 代码优化与工程级应用》&#xff0c;基于VSCodeCmake无痛实现SmartDB。 GitHub路径&#xff1a; smartDB_tutorial 结果展示 主要变化(与SmartDB1.3相比&#xff09; 1&#xff09;使用…

【【萌新的STM32学习-11】】

萌新的STM32学习-11 终于进入了正点原子的入门篇进行一些简单的设计 GPIO General Purpose Input Output 通用输入输出端口 简称GPIO 作用 &#xff1a;负责采集外部器件的信息或者控制外部器件工作&#xff0c;即输入输出 GPIO 的特点 1&#xff0c;不同型号&#xff0c;IO数…

HTML浪漫动态表白代码+音乐(附源码)(二)

一. 前言 七夕马上就要到了&#xff0c;为了帮助大家高效表白&#xff0c;下面再给大家加几款实用的HTML浪漫表白代码(附源码)背景音乐&#xff0c;可用于520&#xff0c;情人节&#xff0c;生日&#xff0c;求爱表白等场景&#xff0c;可直接使用。 来吧&#xff0c;展示&am…

第 7 章 排序算法(3)(选择排序)

7.6选择排序 7.6.1基本介绍 选择式排序也属于内部排序法&#xff0c;是从欲排序的数据中&#xff0c;按指定的规则选出某一元素&#xff0c;再依规定交换位置后达到排序的目的。 7.6.2选择排序思想: 选择排序&#xff08;select sorting&#xff09;也是一种简单的排序方法…

13.PV和PVC

文章目录 PV和PVC概念定义PV定义PVC创建静态PV和PVC创建动态PV和PVCNFS配置创建 Service Account和角色创建存储卷插件创建 StorageClass创建PVC创建pod 总结 PV和PVC 概念 PV 全称叫做 Persistent Volume&#xff0c;持久化存储卷。它是用来描述或者说用来定义一个存储卷的&…

1593页54万字电力行业数字化转型智慧电力云平台整体解决方案WORD

导读&#xff1a;原文《1593页54万字电力行业数字化转型智慧电力一体化监管云平台整体解决方案WORD》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 南方电网一体化…