程序员人生 网站导航

适配器模式 : 农村小伙娶乌克兰美女语言不通 翻译软件立功

栏目:综合技术时间:2016-10-22 13:56:30

不知道甚么时候开始,总听到“ XXX 小伙娶乌克兰美女” 的新闻,比如 农村小伙娶乌克兰美女语言不通 翻译软件立功 等等,我仔细地看了几篇新闻,发现竟然不是标题党,新闻里的乌克兰妹子长得真不错,上几张图:
这里写图片描述
这里写图片描述

看完这些新闻和照片,我心里有3个疑问;
1. 乌克兰真的美女很多吗?
2. 为何乌克兰美女爱嫁给中国男人?
3. 翻译软件可以化腐朽为奇异,软件开发进程中是不是可以参考呢?

经过我大量的研究,得出了答案:

1.乌克兰真的美女很多吗?

这里写图片描述

答:是的。
- 首先从世界地图可以看到,乌克兰地处东欧多个国家交界处,国内民族多达 110 个,各名族之间通婚比较多,长此以往致使混血美女比例比较高。
- 而且,乌克兰的气候环境也比较养人,1年到头冷多热少,阳光直射时间短,致使大多数女孩子皮肤白净。
- 除另外,乌克兰姑娘特别重视外表,打扮的比较精致时尚。

这里写图片描述

2.为何乌克兰美女爱嫁给中国男人?

答:除主观因素外,有两点客观因素很重要。
- 近年乌克兰其实不富裕,距离大家心中的资本主义发达国家还有段距离。1方面生产停滞,经济增长无力;另外一方面,乌克兰还要面临战乱带来的货币贬值、外资流出、物价上涨等压力,财政“只出不进”,全部国家“干耗”外汇储备。所以许多乌克兰姑娘选择外嫁。
- 另外,由于文化、社会福利等缘由,许多乌克兰男人有酗酒、懒惰的习惯,而中国男人在国际上给人1种体贴、勤劳、顾家的形象,所以相较之下,中国男人是比较好的选择。
这里写图片描述
这里写图片描述

3.翻译软件可以化腐朽为奇异,软件开发进程中是不是可以参考呢?

翻译软件把小伙的汉语转换成了乌克兰语,在软件开发进程中这就是1种“复用”!那有甚么设计模式可以到达这类效果呢?

我们先来摹拟实现下这个翻译进程:

a.首先定义1个小目标,就是可以跟妹子说乌克兰语,萨瓦迪卡爱米思油~

/** * description:目标:说乌克兰语 * <br/> * author: shixinzhang * <br/> * data: 9/18/2016 */ public interface Ukrainian { /** * 说乌克兰语,比如:Я люблю тебя * @param string */ void sayUkrainian(String string); }

b.但是理想很饱满,现实很骨感,小伙只会川普:

/** * description:实际情况:只会中文 * <br/> * author: shixinzhang * <br/> * data: 9/18/2016 */ public class Chinese { /** * 说中文,比如:刘奶奶找牛奶奶买榴莲牛奶 * @param string */ void sayChinese(String string) { System.out.println("【中文版】 " + string); } }

c.这时候候翻译器上场了,化腐朽为神器,帮助小伙具有能说乌克兰语的功能:

/** * description:翻译 * <br/> * author: shixinzhang * <br/> * data: 9/18/2016 */ public class Translator implements Ukrainian { private Chinese mChinese; public Translator(Chinese chinese) { mChinese = chinese; } @Override public void sayUkrainian(String string) { //省略了复杂的语法翻译进程,想象1下 mChinese.sayChinese(string); } }

d.可以看到,翻译器持有1个只会中文小伙的援用,实现了说乌克兰语的接口,在需要说乌克兰语的时候,经过语法翻译终究调用小伙的说中文:

@Test public void testAdapterPattern(){ Chinese me = new Chinese(); Ukrainian ukrainianMan = new Translator(me); ukrainianMan.sayUkrainian("我爱你"); }

e.翻译 + 川普小伙 = 乌克兰语达人,运行结果:
这里写图片描述

f.画1下上面这个进程的 UML 图:
这里写图片描述

  • 目标类,即能说乌克兰语,是1个接口;
  • 实际情况,即只能说汉语,是1个既成的、没法改变的类;
  • 中间人,即翻译软件,实现目标接口(乌克兰语),援用了实际情况(中国小伙),经过移花接木,让中国小伙具有了新的功能
  • Client 客户端,乌克兰妹子,希望能和会乌克兰语的人沟通,由于翻译软件实现了乌克兰语接口,因此可以直接实例化1个翻译软件作为乌克兰语人。
@Test public void testAdapterPattern(){ Chinese me = new Chinese(); Ukrainian ukrainianMan = new Translator(me); ukrainianMan.sayUkrainian("我爱你"); }

这就是适配器模式,又称包装模式

定义

将1个类的接口转换为客户希望的另外一个接口。
适配器模式可使本来不兼容的接口变得兼容,即能复用。

1个很形象的例子

这里写图片描述

适配器模式主要分为两种:类适配器和对象适配器

1.对象适配器,与被适配类是关联关系

上面举的例子就是适配器 。Adapter 中持有1个被适配类对象的援用,因此叫做对象适配器。
对象适配器的 UML 图和上述例子1致,所以就偷个懒不列出来了。

2.类适配器,与被适配类是继承关系

Adapter 通过继承被适配类,从而可以调用被适配类的方法。
举个栗子,类适配器下的翻译中介:

/** * description: 类适配器下的翻译中介 * <br/> * author: shixinzhang * <br/> * data: 9/20/2016 */ public class ClassTranslator extends Chinese implements Ukrainian { @Override public void sayUkrainian(String string) { sayChinese(string); } }

采取类适配器模式的翻译软件,继承了被适配类 Chinese,实现了目标接口 Ukrainian,从而使得本来不能使用的 sayChinese(string) 方法可以被调用。

调用时:

@Test public void testClassAdapterPattern(){ Ukrainian ukrainianMan = new ClassTranslator(); ukrainianMan.sayUkrainian("刘奶奶找牛奶奶买榴莲牛奶"); }

这里写图片描述

对照1下对象适配器的代码:

/** * description: 翻译 * <br/> * author: shixinzhang * <br/> * data: 9/18/2016 */ public class Translator implements Ukrainian { private Chinese mChinese; public Translator(Chinese chinese) { mChinese = chinese; } @Override public void sayUkrainian(String string) { mChinese.sayChinese(string); } }

可以看到,对象适配器支持传入1个被适配器对象,因此可以做到对多种被适配接口进行适配,而类适配器直接继承,没法动态修改,所以1般情况下对象适配器使用更广泛。

使用处景:就是想复用,不想多创建!

  1. 通常在软件开发后期或保护期使用,由于这个接口可能已投入使用,但是对新需求不太符合,我们希望尽量复用原有接口,所以用适配器进行包装1下。
    .
  2. 或1开始设计不公道,功能类似,由于参数或名称等细小缘由不能重用时,也能够斟酌包装1下。

《大话设计模式》里看到的1段话很好

  • 事前设计统1接口
  • 问题初现及时重构(下策)
  • 没法改变只能适配(下下策)

后记

说起适配器 Adapter,最熟习的就是 ListView 和 RecyclerVIew 的适配器了,本来准备下1篇就写 ListVIew 源码中的适配器模式,但斟酌到 ListView 中还有视察者模式,所以下1步先总结视察者模式,然后再统1进行 ListView 源码解析


适配器模式和代理模式的区分

从我们这两个设计模式调用的方法可以看出来:

  1. 适配器模式调用时强调“终究要转换成的目的接口”,以本文例子,Translator 终究的目的是变成1个 Ukrainian :
    Ukrainian ukrainianMan = new Translator(me);
    然后客户端调用的是 Ukrainian 的方法
  2. 而代理模式是通过代理,拦截调用,终究以代理类完成工作,以我这篇文章http://blog.csdn.net/u011240877/article/details/52264283 为例 :
    Agent songJJ = new Agent(baoqiang, false);

总结:

适配器模式以到达适配终究接口为目的,
代理模式以拦截、处理为目的。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐