在NBA我需要翻译--适配器模式

1.1 在NBA我需要翻译!

        "你说姚明去了几年,英语练出来了哦,我看教练在那里布置战术,他旁边也没有翻译的,不住点头,瞧样子听懂没什么问题了。"
        "要知道,最开始,有记者问姚明说:'在CBA和NBA最大的区别是什么?',姚明的答案是'在NBA我需要翻译,而在CBA我不需要。'经过几年的锤炼,他的确是在NBA中成长了。不但球技大涨,英语也学得非常棒,用英文答记者问一点问题都没有。不得不佩服呀。"
        "钞票也大大地增加了,他可是中国最富有的体育明星。大鸟呀,你比他还大几岁吧,混得不行呀。"
        "哪能和他比,两米二七的身高,你给我长一个试试。再说,单有身高也是不行的。在NBA现役中锋中,姚明也算是个天才吧。"
"你说当时他刚去美国时,怎么打球呀,什么都听不懂。"
        "之前专门为他配备了翻译的,那个翻译一直在姚明身边,特别是比赛场上,教练、队员与他的对话全部都通过翻译来沟通。"
        "想想看也是,不管多么高球技的球员,如果不懂外语,又没有翻译,球技再高,估计也是不可能在国外待很长时间的。"
        "哦,你等等,你的这个说法,倒让我想起一个设计模式,非常符合你现在提到的这个场景。"

1.2 适配器模式

        "这个模式叫作适配器模式。"
        适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。[DP]
        "适配器模式主要解决什么问题呢?"
        "简单地说,就是需要的东西就在面前,但却不能使用,而短时间又无法改造它,于是我们就想办法适配它。"
        "前面的听懂了,有东西不能用,又不能改造它。但想办法'适配'是什么意思?"


        "其实这个词应该是最早出现在电工学里。我举个例子,电源插座和插头根据国家所在地区的不同,在外形、等级、尺寸和种类方面都有所不同,各个国家都有政府制定的标准。我们出国旅行,自己的手机电脑等充电器与酒店的插座不匹配怎么办?用一个插座转换的适配器就可以了。适配器的意思就是使得一个东西适合另一个东西的东西。"
        "这个我明白,但和适配器模式有什么关系?"
        "哈,NBA篮球运动员都会打篮球,姚明也会打篮球……"
        "废话。"
        "你小子,别打岔。但是姚明却不会英语,要在美国NBA打球,不会英语如何交流?没有交流如何理解教练和同伴的意图?又如何让他们理解自己的想法?不能沟通就打不好球了。于是就有三个办法,第一,让姚明学会英语,你看如何?"
        "这不符合实际呀,姚明刚到NBA打球,之前又没有时间在学校里认真学好英语,马上学到可以听懂会说的地步是很困难的。"
        "说得不错,第二种方法,让教练和球员学会中文?"
        "不可能,那你说怎么办?"
        "给姚明找个翻译。哦,我明白了,你的意思是翻译就是适配器?"
        "对的,在我们不能更改球队的教练、球员和姚明的前提下,我们能做的就是想办法找个适配器。在软件开发中,也就是系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如在需要对早期代码复用一些功能等应用上很有实际价值。"
        "在GoF的设计模式中,对适配器模式讲了两种类型,类适配器模式和对象适配器模式,由于类适配器模式通过多重继承对一个接口与另一个接口进行匹配,而Java、C#、VB.NET等语言都不支持多重继承(C++支持),也就是一个类只有一个父类,所以我们这里主要讲的是对象适配器。"
        适配器模式(Adapter)结构图


Target(这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口)代码如下。
Adaptee(需要适配的类)代码如下。
Adapter(通过在内部包装一个Adaptee对象,把源接口转换成目标接口)代码如下。

package code.chapter17.adapter0;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		Target target = new Adapter();target.request();System.out.println();System.out.println("**********************************************");}
}//需要适配的类
class Adaptee {public void specificRequest(){System.out.println("特殊请求!");}
}//客户期待的接口
class Target {public void request(){System.out.println("普通请求!");}
}//适配器类
class Adapter extends Target {private Adaptee adaptee = new Adaptee(); //建立一个私有的Adaptee对象public void request(){          //这样就可以把表面上调用request()方法adaptee.specificRequest();  //变成实际调用specificRequest()}
}

1.3 何时使用适配器模式

        "你的意思是不是说,在想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式?"
        "对的,两个类所做的事情相同或相似,但是具有不同的接口时要使用它。而且由于类都共享同一个接口,使得客户代码如何?"
        "客户代码可以统一调用同一接口就行了,这样应该可以更简单、更直接、更紧凑。"
        "很好,其实用适配器模式也是无奈之举,很有点'亡羊补牢'的感觉,没办法呀,是软件就有维护的一天,维护就有可能会因不同的开发人员、不同的产品、不同的厂家而造成功能类似而接口不同的情况,此时就是适配器模式大展拳脚的时候了。"
        "你的意思是说,我们通常是在软件开发后期或维护期再考虑使用它?"
        "如果是在设计阶段,你有必要把类似的功能类的接口设计得不同吗?"
        "话是这么说,但不同的程序员定义方法的名称可能不同呀。"
        "首先,公司内部,类和方法的命名应该有规范,最好前期就设计好,然后如果真的如你所说,接口不相同时,首先不应该考虑用适配器,而是应该考虑通过重构统一接口。"
        "明白了,就是要在双方都不太容易修改的时候再使用适配器模式适配,而不是一有不同时就使用它。那有没有设计之初就需要考虑用适配器模式的时候?"
        "当然有,比如公司设计一系统时考虑使用第三方开发组件,而这个组件的接口与我们自己的系统接口是不相同的,而我们也完全没有必要为了迎合它而改动自己的接口,此时尽管是在开发的设计阶段,也是可以考虑用适配器模式来解决接口不同的问题。""好了,说了这么多,你都没有练习一下,来来来,试着把火箭队的比赛,教练叫暂停时给后卫、中锋、前锋分配进攻和防守任务的代码模拟出来。"

1.4 篮球翻译适配器

后卫、中锋、前锋都是球员,所以应该有一个球员抽象类,有进攻和防守的方法。"

package code.chapter17.adapter1;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		Player forwards = new Forwards("巴蒂尔");forwards.attack();Player guards = new Guards("麦克格雷迪");guards.attack();Player center = new Center("姚明");center.attack();center.defense();System.out.println();System.out.println("**********************************************");}
}//球员
abstract class Player {protected String name;public Player(String name){this.name = name;}public abstract void attack();  //进攻public abstract void defense(); //防守
}//前锋
class Forwards extends Player {public Forwards(String name){super(name);}public void attack(){System.out.println("前锋 "+this.name+" 进攻");}public void defense(){System.out.println("前锋 "+this.name+" 防守");}
}//中锋
class Center extends Player {public Center(String name){super(name);}public void attack(){System.out.println("中锋 "+this.name+" 进攻");}public void defense(){System.out.println("中锋 "+this.name+" 防守");}
}//后卫
class Guards extends Player {public Guards(String name){super(name);}public void attack(){System.out.println("后卫 "+this.name+" 进攻");}public void defense(){System.out.println("后卫 "+this.name+" 防守");}
}

"注意,姚明刚来到NBA,他身高够高,球技够好,但是,他那时还不懂英语,也就是说,他听不懂教练的战术安排,attack和defense是什么意思不知道。你这样的写法就是有问题的。事实上,当时是如何解决这个矛盾的?"
"姚明说'我需要翻译。'我知道你的意思了,姚明是外籍中锋,需要有翻译者类来'适配'。"
 

package code.chapter17.adapter2;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		Player forwards = new Forwards("巴蒂尔");forwards.attack();Player guards = new Guards("麦克格雷迪");guards.attack();Player center = new Translator("姚明");center.attack();center.defense();System.out.println();System.out.println("**********************************************");}
}//球员
abstract class Player {protected String name;public Player(String name){this.name = name;}public abstract void attack();  //进攻public abstract void defense(); //防守
}//前锋
class Forwards extends Player {public Forwards(String name){super(name);}public void attack(){System.out.println("前锋 "+this.name+" 进攻");}public void defense(){System.out.println("前锋 "+this.name+" 防守");}
}//中锋
class Center extends Player {public Center(String name){super(name);}public void attack(){System.out.println("中锋 "+this.name+" 进攻");}public void defense(){System.out.println("中锋 "+this.name+" 防守");}
}//后卫
class Guards extends Player {public Guards(String name){super(name);}public void attack(){System.out.println("后卫 "+this.name+" 进攻");}public void defense(){System.out.println("后卫 "+this.name+" 防守");}
}//外籍中锋
class ForeignCenter {private String name;public String getName(){return this.name;}public void setName(String value){this.name = value;}public void 进攻(){System.out.println("外籍中锋 "+this.name+" 进攻");}    public void 防守(){System.out.println("外籍中锋 "+this.name+" 防守");}
}//翻译者类
class Translator extends Player {private ForeignCenter foreignCenter = new ForeignCenter();public Translator(String name){super(name);foreignCenter.setName(name);}public void attack(){foreignCenter.进攻();}public void defense(){foreignCenter.防守();}
}

代码结构图


"这下好了,尽管姚明曾经是不太懂英文,尽管火箭教练和球员也不会学中文,但因为有了翻译者,团队沟通成为可能。

1.5 适配器模式在.NET应用

        "这模式很好用,我想在现实中也很常用的吧。"
        "当然,比如在.NET中有一个类库已经实现的、非常重要的适配器,那就是DataAdapter。DataAdapter用作DataSet和数据源之间的适配器以便检索和保存数据。DataAdapter通过映射Fill(这更改了DataSet中的数据以便与数据源中的数据相匹配)和Update(这更改了数据源中的数据以便与DataSet中的数据相匹配)来提供这一适配器[MSDN]。由于数据源可能是来自SQL Server,可能来自Oracle,也可能来自Access、DB2,这些数据在组织上可能有不同之处,但我们希望得到统一的DataSet(实质是XML数据),此时用DataAdapter就是非常好的手段,我们不必关注不同数据库的数据细节,就可以灵活地使用数据。"
        "啊,DataAdapter我都用了无数次了,原来它就是适配器模式的应用呀,太棒了。我喜欢这个模式,我要经常性地使用它。再比如像Java中的Hibernate开源框架,也是用了类似的方法。"

        "NO!模式乱用不如不用。我给你讲个小故事吧,希望你能理解其深意。"

1.6 扁鹊的医术

        "当年,魏文王问名医扁鹊说:'你们家兄弟三人,都精于医术,到底哪一位最好呢?'扁鹊答:'长兄最好,中兄次之,我最差。'文王再问:'那么为什么你最出名呢?'扁鹊答:'长兄治病,是治病于病情发作之前。由于一般人不知道他事先能铲除病因,所以他的名气无法传出去;中兄治病,是治病于病情初起时。一般人以为他只能治轻微的小病,所以他的名气只及本乡里。而我是治病于病情严重之时。一般人都看到我在经脉上穿针管放血、在皮肤上敷药等大手术,所以大家都以为我的医术高明,名气因此响遍全国。'这个故事说明什么?"
        "啊,你的意思是如果能事先预防接口不同的问题,不匹配问题就不会发生;在有小的接口不统一问题发生时,及时重构,问题不至于扩大;只有碰到无法改变原有设计和代码的情况时,才考虑适配。事后控制不如事中控制,事中控制不如事前控制。"小菜总结说。
        "对呀,如果能事前控制,又何必要事后再去弥补呢?"适配器模式当然是好模式,但如果无视它的应用场合而盲目使用,其实是本末倒置了。"

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

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

相关文章

03-JAVA设计模式-原型模式

原型模式 什么是原型模式 Java原型模式(Prototype Pattern)是一种创建型设计模式,其核心理念在于通过复制(克隆)已有的对象来创建新的对象,而不是通过构造函数来创建。 该模式可以显著提高对象创建的效率…

HTML+CSS+JavaScript网页制作案例教程第2版-黑马程序员-第7章动手实践

7.6 动手实践 学习完前面的内容&#xff0c;下面动手实践一下吧。 请结合给出的素材&#xff0c;运用元素的浮动和定位实现图7-49所示的“焦点图”效果。 链接&#xff1a;https://pan.baidu.com/s/1H98ySBSkd8h3IRA19AV2mw?pwd1024 提取码&#xff1a;1024 index.html <…

代码随想录|Day34|动态规划03|343.整数拆分、96.不同的二叉搜索树

343.整数拆分 动规五步&#xff1a; 确定 dp[i] 含义&#xff1a;拆分数字 i&#xff0c;可以获得的最大乘积为 dp[i]。递推公式&#xff1a;dp[i] max(j * (i - j), j * dp[i - j])。i 可以被拆解为两个数&#xff08;j 和 i - j&#xff09;或者多个数&#xff08;j 和 dp[i…

KMP刷leetcode速通

前言 KMP真厉害&#xff0c;刷题刷到 28.找出字符串中第一个匹配项的下标 和 1668.最大重复子字符串 next 数组用来匹配不上时&#xff0c;前缀 j j j 可以快速回退到 n e x t [ j − 1 ] next[j-1] next[j−1] 的位置。 void getNext(vector<int>& next, const…

5毛钱的DS1302 N/Z串行实时时钟IC

推荐原因&#xff1a; 便宜&#xff0c;够用 该器件最早为DALLAS的产品&#xff0c;所以冠有DS&#xff0c;现国内有多个厂家生产&#xff0c;部分价格不到5毛钱的含税价格&#xff0c;有此自行车&#xff0c;还要什么宝马&#xff1f; 下述为简介&#xff0c;使用前请参阅相应…

Linux 网络配置 主机名解析过程

Windows查看网络信息 ipconfigLinux中查看网络配置&#xff1a; ifconfigVMware的网络编辑器&#xff1a; 测试两台主机网络是否连通&#xff1a; ping ip地址自动获取IP 自动获取IP&#xff0c;可以避免IP冲突&#xff0c;但IP可能会变&#xff0c;使用图形界面&#xf…

xilinx AXI CAN驱动开发

CAN收发方案有很多&#xff0c;常见的解决方案通过是采用CAN收发芯片&#xff0c;例如最常用的SJA1000,xilinx直接将CAN协议栈用纯逻辑实现&#xff0c;AXI CAN是其中一种&#xff1b; 通过这种方式硬件上只需外接一个PHY芯片即可 上图加了一个电平转换芯片 软件设计方面&…

书生·浦语大模型-第三节课笔记/作业

笔记 作业 原版 prompt控制节奏&#xff0c;实现类似关键词检索、主题、信息抽取等功能注意这里根据llm返回的topic (prompt: 告诉我这句话的主题&#xff0c;直接说主题不要解释)进行召回检索(CacheRetriever), 并再次让大模型判断query与返回的检索的相关程度. 如果本地检索…

蓝桥杯 子串简写(暴力)

题目&#xff1a;子串简写 代码1&#xff1a; #include<algorithm> #include<iostream> #include<cstring> #include<queue> #include<cmath>using namespace std;char c1,c2; int k; char s[100010]; int a[100010]; int b[100010]; int cnt; …

Nginx服务 高级配置

五、高级配置 1. 网页的状态页 基于 nginx 模块 ngx_http_stub_status_module 实现&#xff0c;在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module&#xff0c;否则配置完成之后监测会是提示语法错误注意。状态页显示的是整个服务器的状态&#xff0c;而…

Python学习之-logging模块及彩色日志详解

前言&#xff1a; Python的logging模块是内建的、功能强大的日志系统&#xff0c;可通过简单的配置&#xff0c;就能满足基本到复杂的日志管理需求。它可以让你以各种方式记录错误、调试信息、以及其他运行时的信息&#xff0c;这些都是应用程序健壯性、可维护性的关键。 1 基…

分公司=-部门--组合模式

1.1 分公司不就是一部门吗&#xff1f; "我们公司最近接了一个项目&#xff0c;是为一家在全国许多城市都有分销机构的大公司做办公管理系统&#xff0c;总部有人力资源、财务、运营等部门。" "这是很常见的OA系统&#xff0c;需求分析好的话&#xff0…

CTK插件框架学习-服务工厂(06)

CTK插件框架学习-信号槽(05)https://mp.csdn.net/mp_blog/creation/editor/137240105 一、服务工厂定义 注册插件时使用服务工厂注册&#xff0c;使用getService根据调用者插件资源文件内容获取在服务工厂内的对应实现在服务工厂中可以知道是哪个插件正在调用服务工厂懒汉模式…

Day5-Hive的结构和优化、数据文件存储格式

Hive 窗口函数 案例 需求&#xff1a;连续三天登陆的用户数据 步骤&#xff1a; -- 建表 create table logins (username string,log_date string ) row format delimited fields terminated by ; -- 加载数据 load data local inpath /opt/hive_data/login into table log…

开源免费的多功能PDF工具箱

它支持修改PDF、编辑PDF书签、导出PDF书签、导入书签、生成、合并、拆分、提取页面内容、提取图片、OCR 功能介绍: 修改PDF信息&#xff1a;修改文档属性、页码编号、页面链接、页面尺寸&#xff1b;删除自动打开网页等动作&#xff0c;去除复制及打印限制&#xff1b;设置阅读…

别再抱怨学鸿蒙没方向了! 这鸿蒙全栈(南北双向)开发学习路线收藏好!

在互联网技术不断发展的现在&#xff0c;鸿蒙操作系统的出现标志着是能技术领域的一次重大突破&#xff0c;鸿蒙作为华为推出的一代操作系统&#xff0c;鸿蒙不仅达代表了自主创新的力量&#xff0c;还因为独特的分布式架构和全场景适配能力而备受关注。随着鸿蒙生态的不断完善…

2024.4.7周报

摘要 在本周阅读的文献中&#xff0c;提出了基于Transformer的GAN模型&#xff0c;GAN的生成器和鉴别器&#xff0c;都是基于Transformer的编码器架构构建的&#xff0c;通过处理图像的方式处理时间序列数据作为该模型的输入。该模型能够生成各种长度的多维时间序列数据&#…

7.1.4 Selenium 爬取京东商品信息实战

目录 1、实战内容 2、思路 3、分析 url 4、开始操作 1、得到 Cookies 2、访问页面&#xff0c;得到 response 3、解析页面 4、存入 MySQL 5、1-3步总代码 1、实战内容 爬取京东笔记本电脑商品的信息(如&#xff1a;价格、商品名、评论数量)&#xff0c;存入 MySQL 中…

11-新热文章-实时计算

热点文章-实时计算 1 今日内容 1.1 定时计算与实时计算 1.2 今日内容 kafkaStream 什么是流式计算 kafkaStream概述 kafkaStream入门案例 Springboot集成kafkaStream 实时计算 用户行为发送消息 kafkaStream聚合处理消息 更新文章行为数量 替换热点文章数据 2 实时…

能源照明运作机制与智能调控技术实现途径

随着城市化进程的加速&#xff0c;智慧城市已成为现代城市发展的重要方向。能源照明作为城市基础设施的重要组成部分&#xff0c;其运作机制与智能调控技术的实现对于提高城市能源利用效率、促进可持续发展具有重要意义。 能源照明是一个涵盖广泛、错综复杂的领域&#xff0c;它…