




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第第8章章 适配器模式适配器模式(Adapter)2022-4-241结构型模式结构型模式结构型模式概述结构型模式概述 结构型模式结构型模式描述如何将描述如何将类或对象结合在类或对象结合在一起一起形成更大的结构形成更大的结构搭积木,可以通过简单积木的组合形成搭积木,可以通过简单积木的组合形成复杂的、功能更为强大的结构复杂的、功能更为强大的结构结构型模式分为结构型模式分为类结构型模式类结构型模式和和对象结构型模式对象结构型模式:类结构型模式类结构型模式关心类的组合关心类的组合,由多个类可以,由多个类可以组合成一个更大的系统,在类结构型模式中组合成一个更大的系统,在类结构型模式中一般只存在继承关系
2、和实现关系。一般只存在继承关系和实现关系。对象结构型模式对象结构型模式关心类与对象的组合关心类与对象的组合,通过,通过关联关系使得在一个类中定义另一个类的实关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。例对象,然后通过该对象调用其方法。结构型模式结构型模式 根据根据“合成复用原则合成复用原则”,在系统中尽量,在系统中尽量使用组合关系来替代继承关系,因此大使用组合关系来替代继承关系,因此大部分结构型模式都是部分结构型模式都是对象结构型模式对象结构型模式。结构型模式结构型模式结构型模式结构型模式结构型模式简介结构型模式简介 适配器模式适配器模式(Adapter) 桥接模式
3、桥接模式(Bridge) 组合模式组合模式(Composite) 装饰模式装饰模式(Decorator)外观模式外观模式(Facade) 享元模式享元模式(Flyweight) 代理模式代理模式(Proxy) Adapter(适配器适配器)模式模式“不合适的插座不合适的插座”你的电脑的插头是三相的你的电脑的插头是三相的而墙上的插座只有两相的而墙上的插座只有两相的插头和插座的插头和插座的“接口接口”不匹配,怎么办?不匹配,怎么办?Adapter(适配器适配器)模式模式接口转换接口转换面向对象软件系统的适配问题面向对象软件系统的适配问题 假设我们已经有一个软件系统,原来使用假设我们已经有一个软件系
4、统,原来使用了一个了一个第三方类库第三方类库A。现在有一个新的。现在有一个新的第三第三方类库方类库B,其功能等各方面都更加强大。,其功能等各方面都更加强大。 我们希望用我们希望用B来替换来替换A,以改善我们的系统。,以改善我们的系统。但是但是B的接口与的接口与A不一样。那怎么办呢?不一样。那怎么办呢?办法之一办法之一BNew SystemBAdapter办法之二办法之二ASystemBAdapter第二种方案的优点第二种方案的优点System不需要修改代码不需要修改代码不需要修改代码不需要修改代码新代码新代码办法之三办法之三BSystemB示示 例例鸭子接口鸭子接口public interfa
5、ce Duck public void quack();public void fly(); 鸭子接口鸭子接口Duck,定义,定义 鸭子具有鸭子具有“鸣叫鸣叫”和和“飞行飞行”方法方法MallardDuck类类public class MallardDuck implements Duck public void quack() System.out.println(嘎嘎嘎嘎嘎嘎.);public void fly() System.out.println(我在飞哦!我在飞哦!);MallardDuck类简单地类简单地实现了实现了Duck接口接口。现在有一种新家伙现在有一种新家伙public
6、interface Turkey public void gobble();public void fly();WildTurkeypublic class WildTurkey implements Turkey public void gobble() System.out.println(咕咕咕咕咕咕.);public void fly() System.out.println(我在飞,不过飞不远我在飞,不过飞不远);问题?问题?我们我们原来原来有一个程序使用有一个程序使用鸭鸭子对象,子对象,现在现在想让它使用想让它使用火鸡火鸡对象,但是火鸡与鸭子的对象,但是火鸡与鸭子的接口不同,不能直
7、接使用。接口不同,不能直接使用。写一个火鸡适配器,让火鸡看起来像鸭子写一个火鸡适配器,让火鸡看起来像鸭子火鸡适配器火鸡适配器public class TurkeyAdapter implements Duck Turkey turkey;public TurkeyAdapter(Turkey turkey) this.turkey = turkey;public void quack() turkey.gobble();public void fly() for(int i=0; i 5; i+) turkey.fly();火鸡适配器包装了一火鸡适配器包装了一个火鸡对象,同时实个火鸡对象,同时
8、实现了鸭子接口。这样现了鸭子接口。这样就可以像使用鸭子一就可以像使用鸭子一样使用火鸡了样使用火鸡了。使用适配器使用适配器public class DuckTestDrive public static void main(String args) MallardDuck duck = new MallardDuck();WildTurkey turkey = new WildTurkey();Duck turkeyAdapter = new TurkeyAdapter(turkey);System.out.println(火鸡说火鸡说.);turkey.gobble();turkey.fly(
9、);System.out.println(n鸭子说鸭子说.);testDuck(duck);System.out.println(n火鸡适配器说火鸡适配器说.);testDuck(turkeyAdapter); static void testDuck (Duck duck) duck.quack();duck.fly();需要使用鸭子对象需要使用鸭子对象在需要鸭子对象的在需要鸭子对象的地方使用了火鸡适地方使用了火鸡适配器对象,配器对象, 火鸡适火鸡适配器对象包装了一配器对象包装了一个火鸡对象,所以个火鸡对象,所以实际使用的是火鸡实际使用的是火鸡对象。对象。分分 析析被适配者被适配者火鸡接口火
10、鸡接口客户客户要使用鸭子要使用鸭子对象的程序对象的程序适配器适配器把火鸡装把火鸡装扮成鸭子扮成鸭子目标接口目标接口:鸭子接口鸭子接口两者无耦合彼此不必知道对方的存在两者无耦合两者无耦合彼此不必知道对方的存在彼此不必知道对方的存在试试看试试看如果希望把鸭子包装成火鸡该怎么做?如果希望把鸭子包装成火鸡该怎么做?写出你的代码写出你的代码DuckAdapterDuckAdapterimport java.util.Random;public class DuckAdapter implements Turkey Duck duck; Random rand;public DuckAdapter(Duc
11、k duck) this.duck = duck;rand = new Random();public void gobble() duck.quack();public void fly() if (rand.nextInt(5) = 0) duck.fly();别名:包装器别名:包装器(Wrapper),变压器模式变压器模式概念理解概念理解适配器模式适配器模式把一个类的接口把一个类的接口( (被适配者被适配者)变换成客户端所期待的另一种)变换成客户端所期待的另一种接口(接口(目标目标),从而使原本因接口原因不匹配而无法一起),从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。工
12、作的两个类能够一起工作。该模式中涉及有目标、被适配者和适配器。该模式中涉及有目标、被适配者和适配器。 适配器模式的关键是建立一个适配器,这个适适配器模式的关键是建立一个适配器,这个适配器实现了目标接口并包含有被适配者的引用。配器实现了目标接口并包含有被适配者的引用。 适配器模式的结构与使用适配器模式的结构与使用 适配器模式的两种形式:适配器模式的两种形式:类的适配器模式类的适配器模式对象的适配器模式对象的适配器模式 类的适配器模式类的适配器模式(Class Adapter)结构结构Adapter+ request ().Target+ request ().Adaptee+ specificR
13、equest ().ClientspecificRequest();客户客户ClientClient目标(目标(TargetTarget) 客户所期待的接口客户所期待的接口被适配者(被适配者(AdapteeAdaptee):一个已经存在的、需):一个已经存在的、需要适配的类,它具有要适配的类,它具有ClientClient要求的功能但不符要求的功能但不符合合ClientClient的接口要求的接口要求适配器(适配器(AdapterAdapter)对对AdapteeAdaptee的接口与的接口与TargetTarget接口进行适配接口进行适配适配器模式的核心类适配器模式的核心类 被适配者被适配者
14、Adaptee类类没有没有Request方法,而客方法,而客户期待这个方法户期待这个方法 为使客户能够使用为使客户能够使用Adaptee类,提供一个中类,提供一个中间环节,即类间环节,即类Adapter类类 Adapter类实现类实现Target接口,接口,继承继承Adaptee,Adapter的的Request方法重新封装方法重新封装Adaptee的的SpecificRequest方法,实现适配的目的方法,实现适配的目的/目标目标public interface ITarget / Methods void Request(); /被适配者被适配者public class Adaptee /
15、 Methods public void SpecificRequest() System.out.println(Called SpecificRequest() ); / 适配器适配器public class Adapter extends Adaptee implements ITarget public void Request() this.SpecificRequest(); public class Client public static void main(String args) ITarget t = new Adapter(); t.Request(); 类适配器效果类
16、适配器效果 用用Adapter类对类对Adaptee和和Target进行匹配。进行匹配。当想要匹配一个类以及所有它的子类时,当想要匹配一个类以及所有它的子类时,类类Adapter将将不能胜任不能胜任工作工作 使得使得Adapter可以重定义可以重定义Adaptee的部分行的部分行为,因为为,因为Adapter是是Adaptee的一个子类。的一个子类。 仅仅引入一个对象,并不需要额外的指针仅仅引入一个对象,并不需要额外的指针以间接得到以间接得到adaptee对象适配器模式对象适配器模式(Object Adapter)结构结构adapteeAdapter+ request ().Adaptee+
17、specificRequest ().Clientadaptee.specificRequest();Target+ request (). 客户端需要调用客户端需要调用Request方法,而方法,而Adaptee没没有该方法,为了使客户端能够使用有该方法,为了使客户端能够使用Adaptee类,需要提供类类,需要提供类Adapter Adapter包装一个包装一个Adaptee的的实例实例,从而将客,从而将客户端与户端与Adaptee衔接起来衔接起来 由于由于Adapter与与Adaptee是是委派委派关系,这决定关系,这决定了这个适配器模式是对象的了这个适配器模式是对象的 /目标目标publ
18、ic interface ITarget / Methods void Request(); /被适配者被适配者public class Adaptee public void SpecificRequest() / Methods System.out.println(Called SpecificRequest() ); / 适配器适配器public class Adapter implements ITarget Adaptee adaptee = new Adaptee(); public void Request() adaptee.SpecificRequest(); public
19、 class Client public static void main(String args) ITarget t = new Adapter(); t.Request(); 允许一个允许一个Adapter与多个与多个Adaptee及它们所及它们所有子类同时工作。有子类同时工作。Adapter也可以一次给也可以一次给所有的所有的Adaptee添加功能添加功能 使得重定义使得重定义Adaptee的行为比较困难。这的行为比较困难。这就需要生成就需要生成Adaptee的子类并且使得的子类并且使得Adapter引用引用这个子类而不是引用这个子类而不是引用Adaptee本身。本身。对象适配器效果对
20、象适配器效果双向适配器双向适配器 在对象适配器的使用过程中,如果在在对象适配器的使用过程中,如果在适配适配器器中中同时同时包含对包含对目标类目标类和和适配者类适配者类的引用的引用适配者适配者可以通过它调用可以通过它调用目标类目标类中的方法,中的方法,目标类目标类也可以通过它调用也可以通过它调用适配者类适配者类中的方中的方法,那么该适配器就是一个法,那么该适配器就是一个双向适配器双向适配器。adapteetargetAdapter-adapteetarget: Adaptee: Target+request ()specificRequest ()setTarget (Target target
21、)setAdaptee (Adaptee adaptee).Target+ request ().adaptee.specificRequest();Adaptee+ specificRequest ().target.request();ConcreteTarget+ request ().ConcreteAdaptee+ specificRequest ().双向适配器双向适配器 应用举例应用举例 有两个编译好的有两个编译好的(无源代码无源代码)类,类,类类A有某功能。但需有某功能。但需要一个要一个xml读取读取模块模块才能工作,此模块要实现如下才能工作,此模块要实现如下接口接口: (目标
22、目标) public interface XmlReader public InputStream xmlReader(); 另一个另一个类类B恰好有这个功能,但是恰好有这个功能,但是B实现的接口实现的接口:(被被适配者适配者) ) public interface ReaderXml public InputStream readerXml();public class BAdapter implements XmlReader ReaderXml b = new B(); public InputStream xmlReader() return b.readerXml(); 适配器如何写
23、适配器如何写?JDBC使得使得Java语言程序能够与数据库连接语言程序能够与数据库连接JDBC给出一个客户端通用的抽象接口,每给出一个客户端通用的抽象接口,每一个具体数据库引擎的一个具体数据库引擎的JDBC驱动软件都是驱动软件都是一个介于一个介于JDBC接口和数据库引擎接口之间接口和数据库引擎接口之间的适配器软件。的适配器软件。抽象的抽象的JDBC接口和各个数据库引擎接口和各个数据库引擎API之之间都需要相应的间都需要相应的适配器适配器软件,这就是为各软件,这就是为各个不同数据库引擎准备的个不同数据库引擎准备的驱动程序驱动程序。应用举例应用举例分析以下例子,确定各个类的角色分析以下例子,确定各
24、个类的角色public class WebFormDesigner extends JFrame void jbInit() throws Exception text.addActionListener(new WebFormDesigner_text_actionAdapter(this); void text_actionPerformed(ActionEvent e)TextDialog createText = new TextDialog();createText.setVisible(true);createText.setTitle(TEXT);createText.setBo
25、unds(100, 100, 500, 300);createText.setModal(true);createText.show();分析以下例子,确定各个类的角色分析以下例子,确定各个类的角色(续续)class WebFormDesigner_text_actionAdapter implements java.awt.event.ActionListener WebFormDesigner adaptee; WebFormDesigner_text_actionAdapter( WebFormDesigner adaptee) this.adaptee = adaptee;public
26、 void actionPerformed(ActionEvent e) adaptee.text_actionPerformed(e);分析分析WebFormDesigner在本例中是在本例中是AdapteeWebFormDesigner_text_actionAdapter在本例中是在本例中是Adapter, java.awt.event.ActionListener在本例中是适配目标。在本例中是适配目标。适配目标为一接口,代码如下:适配目标为一接口,代码如下:public interface ActionListener extends EventListener /* Invoked
27、when an action occurs.*/public void actionPerformed(ActionEvent e);分析分析适配目标中只有一个方法:适配目标中只有一个方法:actionPerformed()。()。actionPerformed方法是引用了方法是引用了WebFormDesigner这这adaptee来完成的。来完成的。 WebFormDesigner是是WebFormDesigner_text_actionAdapter的方法的方法的参数的参数所以所以WebFormDesigner_text_actionAdapter依赖依赖WebFormDesigner。分
28、析分析Adaptee类(类(WebFormDesigner)的方法)的方法(text_actionPerformed)与与Adapter类类(WebFormDesigner_text_actionAdapte)的方法(的方法(actionPerformed)不同名而实现相同)不同名而实现相同功能功能这就是上面分析的基于对象的这就是上面分析的基于对象的Adapter模式模式。Java中的应用中的应用Iterator适配器(对象的适适配器(对象的适配器模式)配器模式)Java中的应用中的应用Enumeration适配器(对象适配器(对象的适配器模式)的适配器模式)Java中的应用中的应用I/O字节
29、流到字符流的适配字节流到字符流的适配器(对象的适配器模式)器(对象的适配器模式) ByteArrayInputStream, FileInputStream, OutputStream, ReaderJava中的应用中的应用1. Public class FileInputStream extends InputStream 2. private FileDescriptor fd; 3. public FileInputStream(FileDescriptor fdObj) 4. SecurityManager security = System.getSecurityManager();
30、 5. if (fdObj = null) throw new NullPointerException(); 6. if (security != null) security.checkRead(fdObj); 7. fd = fdObj; 8. 9. public FileInputStream(File file) throws FileNotFoundException 10. String name = file.getPath(); 11. SecurityManager security = System.getSecurityManager(); 12. if (securi
31、ty != null) security.checkRead(name); 13. fd = new FileDescriptor(); /对象适配器对象适配器 14. open(name); 15. 16 /其它代码其它代码 17. JDK FileInputStream Torque项目是项目是Apache的公开源代码项目的公开源代码项目,主要用于主要用于生成访问数据库的资源和生成访问数据库的资源和java代码、提供使用这代码、提供使用这些代码访问数据库的运行时些代码访问数据库的运行时(runtime)环境环境 svn checkout /repos
32、/asf/db/torque/trunks接口类:接口类:DB.java抽象类:抽象类:AbstractDBAdapter.java具体实现类:具体实现类:DBOracle.java 连接连接oracle DBMSSQL.java 连接连接SQL Server DBSybase.java 连接连接Sysbase 上述类均继承上述类均继承AbstractDBAdapter.java使用使用Torque访问数据库访问数据库Java Servlet没有从根本上支持网络文件上传没有从根本上支持网络文件上传从而延生从而延生commonsUpload, cos等类库等类库在在Service定义一个定义一个
33、UploadFile接口接口,所有所有Service层层接受的只是接受的只是UploadFile的实现类的实例的实现类的实例,从而统一从而统一了所有了所有Service的调用的调用,而且也使而且也使Service可以在各种可以在各种MVC或者第三方类库中迁移或者第三方类库中迁移. Java Servlet 文件上传问题文件上传问题public interface UploadFile public byte getBytes(); public String getContentType(); public InputStream getInputStream(); public String
34、 getName(); public String getOriginalFilename(); public long getSize(); public boolean isEmpty(); public void transferTo(File dest); Java Servlet 文件上传问题文件上传问题将目标类和适配者类解耦将目标类和适配者类解耦,通过引入一个适配器类,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。来重用现有的适配者类,而无须修改原有代码。增加了类的透明性和复用性增加了类的透明性和复用性,将具体的实现封装在,将具体的实现封装在适配者类中,对于客户端类
35、来说是透明的,而且提适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。高了适配者的复用性。灵活性和扩展性都非常好灵活性和扩展性都非常好,通过使用配置文件,可,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合的基础上增加新的适配器类,完全符合“开闭原开闭原则则”。 适配器模式的优缺点适配器模式的优缺点 适配器模式的优缺点适配器模式的优缺点 类适配器模式优点:类适配器模式优点:由于适配器类是适配者类的子类,因此由于适配器类是适配者类的子类,因此可以在适可以在适配器类中置换一些适配者的方法,使
36、得适配器的配器类中置换一些适配者的方法,使得适配器的灵活性更强灵活性更强。类适配器模式缺点:类适配器模式缺点:对于不支持多重继承的语言,一次最多只能适配对于不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,不能为具体类,其使用有一定的局限性其使用有一定的局限性,不能将,不能将一个适配者类和它的子类都适配到目标接口。一个适配者类和它的子类都适配到目标接口。对象适配器模式优点:对象适配器模式优点:一个对象适配器可以把多个不同的适配者适配到同一个目标,一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,也就是说,同一个适配器可以把适
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 濮阳职业技术学院《文献检索与学术前沿1》2023-2024学年第二学期期末试卷
- 东华理工大学《伟大的红楼梦》2023-2024学年第二学期期末试卷
- 幼儿安全教育:烟花炮竹
- 一杯水压力管理
- 小学一年级安全知识
- 手动叉车安全操作规程
- 抗生素分级管理使用
- 护理专业知识小讲堂
- 2025导游证-《政策与法律法规》考前通关必练题库-含答案
- 医院普通病房管理
- 马凡氏综合征与妊娠
- 导游资格-政策与法律法规考点知识点总结归纳3-第一篇-第二章-宪法基本知识(一)
- 专题34 送东阳马生序(含答案与解析)-备战2024年中考语文之文言文对比阅读(全国版)
- 中职教育二年级上学期《现代物流综合作业-22配送车辆及路线选择》教学课件
- 支持企业建设中试平台实施方案
- 《永远永远爱你》
- 2024年四川省南充市中考历史试卷真题(含官方答案及解析)
- DLT 572-2021 电力变压器运行规程
- 医院进修申请表
- 纸品代理经销协议
- 营养风险筛查与评估课件(完整版)
评论
0/150
提交评论