在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 扁鹊的医术

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验

写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈。 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录&a…

激光雷达和相机的联合标定工具箱[cam_lidar_calibration]介绍

激光雷达和相机的联合标定工具箱[cam_lidar_calibration]介绍 写在前面安装过程调试过程标定成功可视化展示 写在前面 激光雷达和相机联合标定工具 论文地址:https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber9564700 github地址: https://github.com…

设计方案:914-基于64路AD的DBF波束形成硬件

一、硬件概述 DBF技术的实现全部是在数字域实现,然而天线阵列接收的信号经过多次混频后得到的中频信号是模拟信号,实现DBF处理并充分发挥DB&…

[C++][算法基础]模拟堆(堆)

维护一个集合,初始时集合为空,支持如下几种操作: I x,插入一个数 x;PM,输出当前集合中的最小值;DM,删除当前集合中的最小值(数据保证此时的最小值唯一)&…

【LeetCode热题100】153. 寻找旋转排序数组中的最小值(二分)

一.题目要求 已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]若旋转 7…

Flutter应用发布前的关键iOS设备测试策略

大家好,我是咕噜铁蛋!今天我想和大家分享一下关于Flutter应用在发布前,如何进行关键iOS设备测试的策略。随着移动应用的普及,Flutter作为一种跨平台的开发框架,越来越受到开发者的青睐。但是,跨平台也意味着…

10 Python进阶:MongoDB

MongoDb介绍 MongoDB是一个基于分布式架构的文档数据库,它使用JSON样式的数据存储,支持动态查询,完全索引。MongoDB是NoSQL数据库的一种,主要用于处理大型、半结构化或无结构化的数据。以下是MongoDB数据库的一些关键特点和优势&a…

蓝桥杯 历届真题 杨辉三角形【第十二届】【省赛】【C组】

资源限制 内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 思路: 由于我第一写没考虑到大数据的原因,直接判断导致只得了40分,下面是我的代码: #…

4.7 IO day6

1&#xff1a;有一个隧道&#xff0c;全长5公里&#xff0c;有2列火车&#xff0c;全长200米&#xff0c; 火车A时速 100公里每小时 火车B时速 50公里每小时 现在要求模拟火车反复通过隧道的场景(不可能2列火车都在隧道内运行) #include <stdio.h> #include <string.…

1、java语法入门(找工作版)

文章目录 一、Java简介二、Java常量与变量1、标识符2、关键字3、变量4、类的命名规则5、数据类型6、基本数据类型字面值7、变量的定义与初始化8、ASCII码和Unicode编码9、转义字符10、类型转换11、常量 三、Java运算符1、算术运算符2、赋值运算符3、关系运算符4、逻辑运算符5、…

C#/.NET/.NET Core推荐学习书籍(24年4月更新,已分类)

前言 古人云&#xff1a;“书中自有黄金屋&#xff0c;书中自有颜如玉”&#xff0c;说明了书籍的重要性。作为程序员&#xff0c;我们需要不断学习以提升自己的核心竞争力。以下是一些优秀的C#/.NET/.NET Core相关学习书籍&#xff08;包含了C#、.NET、.NET Core、Linq、EF/E…

瓦拉纳西(Varanasi)宗教重要性历史与文化旅游与经济社会生活环境挑战“赶due”赶due的特点包括:赶due的应对策略:陶行知生平简介教育实践与贡献

目录 瓦拉纳西&#xff08;Varanasi&#xff09; 宗教重要性 历史与文化 旅游与经济 社会生活 环境挑战 “赶due” 赶due的特点包括&#xff1a; 赶due的应对策略&#xff1a; 陶行知 生平简介 教育实践与贡献 教育思想 遗产与影响 1.澳洲限制半工半读&#xff…

SQL Sever 2008 安装教程

先从官网下载程序&#xff1a;下载地址 打开上述链接后&#xff0c;点击下载按钮。 就会跳出下面这个界面&#xff0c;如果你的电脑是64位的请选择下图中这两个程序。 下载完成后&#xff0c;在电脑磁盘中找到这两个文件&#xff0c;注意安装的顺序&#xff0c;先安装 SQLEXPR…

H5 点击图片翻转效果

需求 ☑ h5 实现点击图片得到的是放大的镜像图片&#xff08;不是放大镜效果 而是实现图片镜像对折&#xff0c;左右翻转&#xff09; ☑ 鼠标点击后原图消失/隐藏&#xff0c;在原来的位置上取而代之的是翻转后的图&#xff08;除了翻转之外不要改变其他的性质&#xff0c;比…

如何保证全部流量走代理

最近因为某些原因&#xff0c;需要做一些确保高匿的事情&#xff0c;便花时间做了一定的调研&#xff0c;至于是什么事情这里不便多说。 本文主要还是聊聊我看到的一些使用代理软件误区和确保流量全部走代理的方法&#xff0c;甚至也可以说是Proxifier的用户使用手册&#xff…

2024/4/1—力扣—栈的最小值

代码实现&#xff1a; typedef struct node {int val;struct node *next; } Node;typedef struct {struct node *top;int min; } MinStack;/** initialize your data structure here. */MinStack* minStackCreate() {MinStack *obj malloc(sizeof(*obj));obj->top NULL;ob…

Redis分布式锁误删情况说明

4.4 Redis分布式锁误删情况说明 逻辑说明&#xff1a; 持有锁的线程在锁的内部出现了阻塞&#xff0c;导致他的锁自动释放&#xff0c;这时其他线程&#xff0c;线程2来尝试获得锁&#xff0c;就拿到了这把锁&#xff0c;然后线程2在持有锁执行过程中&#xff0c;线程1反应过…

Open-GroundingDino和GroundingDino的推理流程实现

1、简单介绍 GroundingDino是一个多模态检测模型&#xff0c;可以输入文本提示输出视觉目标的位置&#xff0c;实现了文本和图像的匹配。相比较于一众的OVD算法&#xff0c;GroundingDino在文本处理上的灵活度高&#xff0c;因为大多OVD算法是采用clip文本编码器&#xff0c;这…

1.8.4 卷积神经网络近年来在结构设计上的主要发展和变迁——Inception-v2 和Inception-v3

1.8.4 卷积神经网络近年来在结构设计上的主要发展和变迁——Inception-v2 和Inception-v3 前情回顾&#xff1a; 1.8.1 卷积神经网络近年来在结构设计上的主要发展和变迁——AlexNet 1.8.2 卷积神经网络近年来在结构设计上的主要发展和变迁——VGGNet 1.8.3 卷积神经网络近年来…

C# Solidworks二次开发:获取唯一ID的API详解

大家好&#xff0c;今天要介绍的是关于solidworks中可以获取对象唯一ID的几种API&#xff0c;获取唯一ID的API有如下几种&#xff1a; &#xff08;1&#xff09;第一种是GetID Method (IComponent2)&#xff0c;其含义为获取每个组件的唯一ID。 下面是API中的使用例子&#x…