适配器模式
2016-05-21 10:22
507 查看
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工
作,就是适配器模式。
它主要能解决的应用场景是在:系统的数据和行为都正确,但是接口不符合时,且双方都不方便修改自己对外接
口时,这是就可以采用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望
复用一些现存的类,但是接口却又与复用环境要求不一致的情况。比如:需要复用早期其他项目的一些功能。
适配器的类图:
由上图中,我们可以分析出模式中的角色有:
1、目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
2、需要适配的类(Adaptee):需要适配的类或适配者类。
3、适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
而Client类最终面对的是 Target 接口(或抽象类),它只能够使用符合这一目标标准的子类。
使用适配器模式的优势在于:
1、通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。简单、直接、紧凑。
2、复用了现存的类,解决了现存类和复用环境要求不一致的问题。
3、将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
4、一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和
它的子类都适配到目标接口。
但是适配器模式也有其缺陷,如果早期双发就统一了接口,就不会有适配器模式的存在了,当然针对不同的厂商,接
口不一致,这是使用适配器就很合适。很多人分不清代理模式与适配器模式有合不同,确实粗略的看起来,都是提供
一个对外的接口, 隐藏真实的自己。但是细分下来,还是能区分,一个重在代理,行为方法都必须要一模一样。而适
配却不是,它重在适配,是要求按照客户的要求去适配,它的行为方法需要要客户要求保持一致。
如下示例:
我这里也采用《大话设计模式》中的例子,很有趣。它这个例子有3种角色的存在:分别是教练(客服端),
教员(如:巴蒂尔,麦迪, 姚明等,但是姚明来自中国,听不明白英文 ,需要适配),翻译(适配者)
我们先来设计一个球员抽象类,行为提供:进攻,防守
再分别定义3个子类,分别是:前锋,中锋,后卫 实现上述接口
再定义一个教练类,用于训练,发出指令
得到的结果是:
对于巴蒂尔,麦迪而言,教练的指令很容易就接收到了,但是姚明,来自中国,却无法理解Attack代表什么意思,导致他一头雾水的战在原地不知道干啥,这是我们的翻译就来了。
我们先定义一个外籍球类,用于他们本国训练
然后再给这个外籍球员类,添加一个翻译,适配器类
最后我们再修改下教练类
这时运行的结果就是:
好,这时姚明也可以正常参与到训练了。
最后,我们看下整个训练计划的类图:
最后,依然要说明的是:适配器很像“亡羊补牢”,如何可以在早期就定义好,就不存在适配的问题了。
作,就是适配器模式。
它主要能解决的应用场景是在:系统的数据和行为都正确,但是接口不符合时,且双方都不方便修改自己对外接
口时,这是就可以采用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望
复用一些现存的类,但是接口却又与复用环境要求不一致的情况。比如:需要复用早期其他项目的一些功能。
适配器的类图:
由上图中,我们可以分析出模式中的角色有:
1、目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
2、需要适配的类(Adaptee):需要适配的类或适配者类。
3、适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
而Client类最终面对的是 Target 接口(或抽象类),它只能够使用符合这一目标标准的子类。
使用适配器模式的优势在于:
1、通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。简单、直接、紧凑。
2、复用了现存的类,解决了现存类和复用环境要求不一致的问题。
3、将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
4、一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和
它的子类都适配到目标接口。
但是适配器模式也有其缺陷,如果早期双发就统一了接口,就不会有适配器模式的存在了,当然针对不同的厂商,接
口不一致,这是使用适配器就很合适。很多人分不清代理模式与适配器模式有合不同,确实粗略的看起来,都是提供
一个对外的接口, 隐藏真实的自己。但是细分下来,还是能区分,一个重在代理,行为方法都必须要一模一样。而适
配却不是,它重在适配,是要求按照客户的要求去适配,它的行为方法需要要客户要求保持一致。
如下示例:
我这里也采用《大话设计模式》中的例子,很有趣。它这个例子有3种角色的存在:分别是教练(客服端),
教员(如:巴蒂尔,麦迪, 姚明等,但是姚明来自中国,听不明白英文 ,需要适配),翻译(适配者)
我们先来设计一个球员抽象类,行为提供:进攻,防守
package com.my.adapter.player; /** * 定义一个球员抽象接口 * * @author Administrator * */ public interface IPlayer { /** * 定义一个进攻方法 */ public void attack(); /** * 定义一个防守方法 */ public void defense(); }
再分别定义3个子类,分别是:前锋,中锋,后卫 实现上述接口
package com.my.adapter.player; /** * 定义一个前锋类,实现Player接口 * * @author Administrator * */ public class ForwardsPlayer implements IPlayer { private String name; public ForwardsPlayer() { super(); // TODO Auto-generated constructor stub } public ForwardsPlayer(String name) { // TODO Auto-generated constructor stub this.name = name; } @Override public void attack() { // TODO Auto-generated method stub System.out.println(name + " Attack!"); } @Override public void defense() { // TODO Auto-generated method stub System.out.println(name + " Defense!"); } }
package com.my.adapter.player; /** * 定义一个中锋类,实现Player接口 * * @author Administrator * */ public class CenterPlayer implements IPlayer { private String name; public CenterPlayer() { super(); // TODO Auto-generated constructor stub } public CenterPlayer(String name) { // TODO Auto-generated constructor stub this.name = name; } @Override public void attack() { // TODO Auto-generated method stub System.out.println(name + " Attack!"); } @Override public void defense() { // TODO Auto-generated method stub System.out.println(name + " Defense!"); } }
package com.my.adapter.player; /** * 定义一个后卫类,实现Player接口 * * @author Administrator * */ public class GuardsPlayer implements IPlayer { private String name; public GuardsPlayer() { super(); // TODO Auto-generated constructor stub } public GuardsPlayer(String name) { // TODO Auto-generated constructor stub this.name = name; } @Override public void attack() { // TODO Auto-generated method stub System.out.println(name + " Attack!"); } @Override public void defense() { // TODO Auto-generated method stub System.out.println(name + " Defense!"); } }
再定义一个教练类,用于训练,发出指令
package com.my.adapter.client; import com.my.adapter.player.CenterPlayer; import com.my.adapter.player.ForwardsPlayer; import com.my.adapter.player.GuardsPlayer; import com.my.adapter.player.IPlayer; public class Trainer { public static void main(String[] args) { // 训练队员 IPlayer forward = new ForwardsPlayer("巴蒂尔"); forward.attack(); IPlayer guard = new GuardsPlayer("麦迪"); guard.defense(); IPlayer center = new CenterPlayer("姚明"); center.attack(); } }
得到的结果是:
巴蒂尔 Attack! 麦迪 Defense! 姚明 Attack!
对于巴蒂尔,麦迪而言,教练的指令很容易就接收到了,但是姚明,来自中国,却无法理解Attack代表什么意思,导致他一头雾水的战在原地不知道干啥,这是我们的翻译就来了。
我们先定义一个外籍球类,用于他们本国训练
package com.my.adapter.foreign; /** * 定义一套外籍球员训练行为类 * * @author Administrator * */ public interface IForeignPlayer { public void 进攻(); public void 防守(); }
package com.my.adapter.foreign; /** * 定义一个外籍球员类 * * @author Administrator * */ public class ForeignPlayer implements IForeignPlayer { private String name; public ForeignPlayer() { super(); // TODO Auto-generated constructor stub } public ForeignPlayer(String name) { this.name = name; } @Override public void 进攻() { // TODO Auto-generated method stub System.out.println(name + " 进攻!"); } @Override public void 防守() { // TODO Auto-generated method stub System.out.println(name + " 防守!"); } }
然后再给这个外籍球员类,添加一个翻译,适配器类
package com.my.adapter.adapter; import com.my.adapter.foreign.ForeignPlayer; import com.my.adapter.foreign.IForeignPlayer; import com.my.adapter.player.IPlayer; /** * 翻译类(适配类) * * @author Administrator * */ public class AdapterPlayer implements IPlayer { // 声明外籍球员类 private IForeignPlayer foreign = null; public AdapterPlayer() { super(); // TODO Auto-generated constructor stub } public AdapterPlayer(String name) { super(); foreign = new ForeignPlayer(name); } @Override public void attack() { // TODO Auto-generated method stub foreign.进攻(); } @Override public void defense() { // TODO Auto-generated method stub foreign.防守(); } }
最后我们再修改下教练类
package com.my.adapter.client; import com.my.adapter.adapter.AdapterPlayer; import com.my.adapter.player.CenterPlayer; import com.my.adapter.player.ForwardsPlayer; import com.my.adapter.player.GuardsPlayer; import com.my.adapter.player.IPlayer; public class Trainer { public static void main(String[] args) { // 训练队员 IPlayer forward = new ForwardsPlayer("巴蒂尔"); forward.attack(); IPlayer guard = new GuardsPlayer("麦迪"); guard.defense(); // IPlayer center = new CenterPlayer("姚明"); // center.attack(); IPlayer center = new AdapterPlayer("姚明"); center.attack(); } }
这时运行的结果就是:
巴蒂尔 Attack! 麦迪 Defense! 姚明 进攻!
好,这时姚明也可以正常参与到训练了。
最后,我们看下整个训练计划的类图:
最后,依然要说明的是:适配器很像“亡羊补牢”,如何可以在早期就定义好,就不存在适配的问题了。
相关文章推荐
- Apue学习:高级I/O
- JavaWeb的学习总结(三)— 过滤器(Filter)
- 1:git安装及创建仓库
- 00015:小X 学游泳
- 计算几何常用算法总结
- Struts2之文件上传与下载
- 代理服务器的用途
- 百度地图API的Android开发之申请秘钥
- MAX232和PL2303、CH340的区…
- 使用request.js时遇到的url编码问题
- USB2.0通讯协议
- labview中应用的一些小操作
- c#窗体控件datagriview与dataset的运用:修改,新增,删除,查找,保存,更新
- 转:Labview中引用,属性节点,局…
- matlab中方程求解的基本命令
- 图解Win7下set命令使用
- 网转高速ADC的电源设计
- BCDboot 命令行选项
- 对堆栈8字节对齐问题的讨论…
- NYOJ 题目234 吃土豆