版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
TheAdapter
Pattern
(结构模式之适配器模式)本章主要内容现实生活中的适配器面向对象的适配器适配器的例子适配器模式解析适配器模式概念对象适配器和类适配器Java的迭代器装饰者和适配器模式现实生活中的适配器电压适配当把美国的电器拿回中国大陆去用的时候,就面临电压不同的问题。美国的生活用电压是110伏,而中国的电压是220伏。怎么办?如果要在中国大陆使用在美国使用的电器,就必须有一个能把220伏电压转换成110伏电压的变压器。现实生活中的适配器请大家举例鼠标的串口和usb口之间的转化面向对象软件系统的适配问题假设我们已经有一个软件系统,原来使用了一个第三方类库A。现在有一个新的第三方类库B,其功能等各方面都更加强大。我们希望用B来替换A,以改善我们的系统。但是B的接口与A不一样。那则么办呢?办法之一ASystemBNewSystem办法之一BNewSystemBAdapter办法之二ASystemBAdapter第二种方案的优点System不需要修改代码不需要修改代码新代码办法之三B’SystemB适配器的例子简化的鸭子接口和类publicinterfaceDuck{ publicvoidquack(); publicvoidfly();}鸭子接口Duck,定义了鸭子具有“鸣叫”和“飞行”方法MallardDuck类publicclassMallardDuckimplementsDuck{ publicvoidquack(){ System.out.println("嘎嘎嘎..."); } publicvoidfly(){ System.out.println("我在飞哦!"); }}MallardDuck类简单地实现了Duck接口。现在有一种新家伙publicinterfaceTurkey{ publicvoidgobble(); publicvoidfly();}WildTurkeypublicclassWildTurkeyimplementsTurkey{ publicvoidgobble(){ System.out.println("咕咕咕..."); } publicvoidfly(){ System.out.println("我在飞,不过飞不远。"); }}我们原来有一个程序使用鸭子对象,现在想让它使用火鸡对象,但是火鸡与鸭子的接口不同,不能直接使用。写一个火鸡适配器,让火鸡看起来像鸭子火鸡适配器publicclassTurkeyAdapterimplementsDuck{ Turkeyturkey; publicTurkeyAdapter(Turkeyturkey){ this.turkey=turkey; } publicvoidquack(){ turkey.gobble(); } publicvoidfly(){ for(inti=0;i<5;i++){ turkey.fly(); } }}火鸡适配器包装了一个火鸡对象,同时实现了鸭子接口。这样就可以像使用鸭子一样使用火鸡了。使用适配器publicclassDuckTestDrive{ publicstaticvoidmain(String[]args){ MallardDuckduck=newMallardDuck(); WildTurkeyturkey=newWildTurkey(); DuckturkeyAdapter=newTurkeyAdapter(turkey); System.out.println("火鸡说..."); turkey.gobble(); turkey.fly(); System.out.println("\n鸭子说..."); testDuck(duck); System.out.println("\n火鸡适配器说..."); testDuck(turkeyAdapter); } staticvoidtestDuck(Duckduck){ duck.quack(); duck.fly(); }}需要使用鸭子对象在需要鸭子对象的地方使用了火鸡适配器对象,
火鸡适配器对象包装了一个火鸡对象,所以实际使用的是火鸡对象。适配器模式详解被适配者火鸡接口客户要使用鸭子对象的程序适配器把火鸡装扮成鸭子目标接口:鸭子接口两者无耦合彼此不必知道对方的存在两者无耦合彼此不必知道对方的存在适配器涉及的几个概念客户(client):使用适配器的用户目标接口(targetinter):客户和适配器之间交互的接口适配器(adapter):客户和源之间的中介被适配者接口(adapteeinter):适配器和被适配者(源)之间的接口。被适配者(源)adaptee:试试看现在,如果希望把鸭子包装成火鸡该怎么做?写出你的代码DuckAdapterDuckAdapter参考答案importjava.util.Random;publicclassDuckAdapterimplementsTurkey{ Duckduck; Randomrand; publicDuckAdapter(Duckduck){ this.duck=duck; rand=newRandom(); } publicvoidgobble(){ duck.quack(); } publicvoidfly(){ if(rand.nextInt(5)==0){ duck.fly(); } }}适配器模式“Converttheinterfaceofaclassintoanotherinterfacethattheclientsexpect.Adapterletsclassesworktogetherthatcouldnototherwisebecauseofincompatibleinterfaces”适配器将一个类的接口转化为客户期望的接口类型,可以让一个类与其接口不兼容的类进行交互。Adapter模式定义将一个类的接口转换成客户端所期望的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。别名包装器WrapperClientTargetRequest()AdapteeExistingRequest()AdapterRequest()adapteeAdapter模式动机有时,为复用而设计的工具箱类不能够被复用的原因仅仅是因为它的接口与专业应用领域所需要的接口不匹配。我们可以改变工具箱类使它兼容专业领域中的类的接口,但前提是必须有这个工具箱的源代码。然而即使我们得到了这些源代码,修改工具箱也是没有什么意义的;因为不应该仅仅为了实现一个应用,工具箱就不得不采用一些与特定领域相关的接口。Adapter模式动机(续)我们可以不用上面的方法,而定义一个适配器类,由它来适配工具箱的接口和专业应用的接口。我们可以用两种方法做这件事:1)继承专业应用类的接口和工具箱类的实现。这种方法对应Adapter模式的类版本(多继承)2)将一个工具箱类的实例作为适配器类的组成部分,并且使用工具箱的接口实现适配器类。这种方法对应Adapter模式的对象版本。Adapter模式适用性以下情况使用Adapter模式你想使用一个已经存在的类,而它的接口不符合你的需求。你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。(仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。基于类的Adapter模式基于类的Adapter模式的一般结构如下:Adaptee类为Adapter的父类,Adaptee类为适配源,适配目标(接口)也是Adapter的父类;基于类的Adapter模式比较适合应用于Adapter想修改Adaptee的部分方法的情况。类适配器ClientTargetRequest()AdapteeExistingRequest()AdapterRequest()adaptee1.采用了多继承来实现,java不支持多继承UML系统建模与分析设计基于对象的Adapter模式基于对象的Adapter模式的一般结构如下:Adaptee类对象为Adapter所依赖,适配目标(接口)是Adapter的父类;基于对象的Adapter模式比较适合应用于Adapter想为Adaptee添加新的方法的情况。但在Adaptee类的方法与Adapter类的方法不同名而实现相同功能的情况下,我们一般也使用基于对象的Adapter模式,Adapter模式效果(类适配器和对象适配器有不同的权衡)类适配器用一个具体的Adapter类对Adaptee和Target进行匹配。结果是当我们想要匹配一个类以及所有它的子类时,类Adapter将不能胜任工作。使得Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类。仅仅引入了一个对象,并不需要额外的指针以间接得到adaptee。Adapter模式效果(类适配器和对象适配器有不同的权衡)对象适配器则允许一个Adapter与多个Adaptee—即Adaptee本身以及它的所有子类(如果有子类的话)同时工作。Adapter也可以一次给所有的Adaptee添加功能。使得重定义Adaptee的行为比较困难。这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。Java中的迭代器早期的Java中有枚举器,Enumeration,可以逐个遍历集合中的每一个元素,而不需要知道,集合中元素的结构。publicinterfaceEnumeration{publicbooleanhasMoreElements();publicObjectnextElements();}迭代器Sun公司更新了接口,采用Iterator(迭代器)接口,和枚举器非常相似,但扩展了功能。
publicinterfaceIterator{publicbooleanhasNext();publicObjectnext();publicvoidremove();}枚举器和迭代器之间非常相似,但有个方法不同。remove方法现在,我们面对了有枚举器的接口的库函数,如何让客户使用迭代器,我们需要适配器。客户?源:适配器?设计适配器ClientIteratorRequest()EnumerationExistingRequest()EnumeratinIteratorAdapterRequest()adaptee代码publicclassEnumerationIteratorimplementsIterator{Enumerationenum;publicEnumerationIterator(Enumerationenum){this.enum=enum;}publicbooleanhasNext(){returnenum.hasMoreElements();}publicObjectnext(){returnenum.nextElement();}publicvoidremove(){thrownewException():}}问题如果现在面对使用了枚举器接口的客户代码,而库函数使用了迭代器,如何实现?适配器模式VS装饰者模式相似点:都是包装源。不同点:使用适配器的原因是因为接口不匹配;而使用装饰模式是因为功能有欠缺,但不改变接口。这两个在概念上还是不一样的。
装饰者模式就是为原有对象新增加一个功能,新的装饰者对象>=原有对象.
Decoratorenhancesanotherobjectwithoutchanginginterface利用适配器模式指方为圆 中国古代有赵高指鹿为马的故事。鹿与马有很多相似之处,没见过的人本就分辨不清,指一指可能没什么大不了的。指方为圆是否太过?非也。本例就是要指方为圆,需要的只是适配器模式这个魔术手指(MagicFinger)。 publicclassCube{publicCube(doublewidth){this.width=width;}publicdoublecalculateVolume(){returnwidth*width*width;}publicdoublecalculateFaceArea(){returnwidth*width;}publicdoublegetWidth(){returnthis.width;}publicvoidsetWidth(doublewidth){this.width=width;}privatedoublewidth;}publicinterfaceBallIF{doublecalculateArea();doublecalculateVolume();doublegetRadius();voidsetRadius(doubleradius);}publicclassMagicFingerimplementsBallIF{publicMagicFinger(Cubeadaptee){super();this.adaptee=adaptee;radius=adaptee.getWidth();}publicdoublecalculateArea(){returnPI*4.0D*(radius*radius);}publicdoublecalculateVolume(){returnPI*4.0D/3.0D*(radius*radius*radius);} publicdoublegetRadius(){returnradius;}publicvoidsetRadius(doubleradius){this.radius=radius;}privatedoubleradius=0;privatestaticfinaldoublePI=3.14D;privateCubeadaptee;} 还记得中学的数学的话,应该可以看出,我们的指方为圆系统其实还是有道理的。它接受一个正方体,返还此正方体的内切球,也就是能放进此正方体的最大的球。 问题如何实现指圆为方。画出类图,给出源码。请做一个小猫(kittie)的实类,并实现miao(),catchRat(),run(),sleep()等方法。再做一个小狗(doggie)的接口,要求有wao(),fetchBall(),run(),sleep()等方法。现在你的女朋友想要一只小狗,可是你只找到的一只小猫。请用适配器模式把小猫“适配成”小狗,让你的女(男)朋友满意。(提示:量力而为。)编写一个测试主类,测试你的程序GoF’sFacadePatternMakeitsimplerDefinesahigher-levelinterfacethatmakesthesubsystemeasiertouse外观模式Provideaunifiedinterfacetoasetofinterfacesinasubsystem.Façadedefinesahigher-levelinterfacethatmakesthesubsystemeasiertouse.”为一个子系统的一批接口提供一个统一标准的接口,Facade定义更高层次的接口,使得子系统更容易使用。目的provideunifiedinterfacetoasetofinterfaces为一系列接口集提供统一的接口makessubsystemeasiertouse使得子系统易用作用minimizedependenciesbetweensubsystems降低子系统的依赖性tiestogetherclassesthatprovidesubsystemfunctionalitywithouttotallyhidingclasses将类紧密联系在一起提供子系统的功能,并不完全掩藏类。适用性providesimpleinterfacetocomplexsubsystem为复杂子系统提高简单接口helpdecouplesubsyst
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024版工程市场推广与营销合同2篇
- 期权协议书1000字模板
- 四方合作经营协议书
- 配电室2024年度电缆线路敷设及接头处理合同
- 小额信用贷款借款合同
- 承包物流合同范本
- 《治疗方法》课件
- 2024年度校园食品安全管理与服务合同3篇
- 人教版九年级化学第十单元实验活动7溶液酸碱性的检验分层作业课件
- 人教版九年级化学第一单元3走进化学实验室课时2物质的加热仪器的连接和洗涤分层作业课件
- GB/T 19342-2024手动牙刷一般要求和检测方法
- 2023-2024学年广东省深圳市南山区八年级(上)期末英语试卷
- GB/T 15822.1-2024无损检测磁粉检测第1部分:总则
- QC080000培训资料课件
- 《研学旅行课程设计》课件-学习情境三 研之有方-研学课程教学设计
- 音乐教师职业生涯发展报告
- 游戏风云:阿里云全球同服游戏方案全面解读
- 35kv线路验收规范
- 薄膜材料 第五章薄膜的形成、生长与结构
- 3--碎石土路基填筑施工工法(完整版)
- 英语四级单词表4500.xls
评论
0/150
提交评论