设计模式-适配器模式
2017-08-21 11:47
190 查看
定义
适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。适配器模式中引入了一个被称为适配器(Adapter)的包装类,而它所包装的对象称为适配者(Adaptee),即被适配的类。适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器让那些由于接口不兼容而不能交互的类可以一起工作。
在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。根据适配器类与适配者类的关系不同,适配器模式可分为对象适配器和类适配器两种,
在对象适配器模式中,适配器与适配者之间是关联关系;
在类适配器模式中,适配器与适配者之间是继承(或实现)关系。
在实际开发中,对象适配器的使用频率更高。
模式中的角色:
目标接口:客户希望的接口适配器类(适配器):将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作
需要适配的类(适配者):需要被转换的类
角色关系UML:
目标接口:微信用户信息数据访问接口
适配器:将微信用户信息转换成自定义用户信息,执行自定义用户信息数据访问操作
需要适配的类:自定义用户信息数据访问实现
UML图如下:
java代码:
目标接口4000
:
package demo15; /** * * @ClassName: WeChatUserInfoDao * @Description:微信用户信息数据访问接口 * @author cheng * @date 2017-8-21 上午11:30:12 */ public interface WeChatUserInfoDao { /** * * @Title: saveWeChatUserIno * @Description:保存 */ void saveWeChatUserIno(); /** * * @Title: updateWeChatUserIno * @Description:更新 */ void updateWeChatUserIno(); }
需要适配的类:
package demo15; /** * * @ClassName: MyUserInfoDaoImpl * @Description:自定义用户信息数据访问实现 * @author cheng * @date 2017-8-21 上午11:32:12 */ public class MyUserInfoDaoImpl { /** * * @Title: saveMyUserInfo * @Description:保存 */ public void saveMyUserInfo() { System.out.println("保存自定义用户信息"); } /** * * @Title: updateMyUserInfo * @Description:更新 */ public void updateMyUserInfo() { System.out.println("更新自定义用户信息"); } }
适配器:
package demo15; /** * * @ClassName: UserInfoDaoAdapter * @Description:用户信息适配器 * @author cheng * @date 2017-8-21 上午11:34:55 */ public class UserInfoDaoAdapter implements WeChatUserInfoDao { // 持有需要适配的类的引用 private MyUserInfoDaoImpl myUserInfoDaoImpl; public UserInfoDaoAdapter() { this.myUserInfoDaoImpl = new MyUserInfoDaoImpl(); } /** * 复写 */ @Override public void saveWeChatUserIno() { System.out.println("微信用户信息转换成自定义用户信息"); //执行适配类的方法 myUserInfoDaoImpl.saveMyUserInfo(); } /** * 复写 */ @Override public void updateWeChatUserIno() { System.out.println("微信用户信息转换成自定义用户信息"); //执行适配类的方法 myUserInfoDaoImpl.updateMyUserInfo(); } }
测试:
package demo15; /** * * @ClassName: ClientTest * @Description:测试 * @author cheng * @date 2017-8-21 上午11:40:20 */ public class ClientTest { public static void main(String[] args) { // 创建目标接口,实现类为适配器类 WeChatUserInfoDao weChatUserInfoDao = new UserInfoDaoAdapter(); System.out.println("==================使用目标接口的保存======================="); //执行目标方法 weChatUserInfoDao.saveWeChatUserIno(); System.out.println("==================使用目标接口的更新======================="); weChatUserInfoDao.updateWeChatUserIno(); } }
运行结果:
总结
适配器模式将现有接口转化为客户类所期望的接口,实现了对现有类的复用,它是一种使用频率非常高的设计模式,在软件开发中得以广泛应用,在 spring 等开源框架、驱动程序设计(如JDBC中的数据库驱动程序)中也使用了适配器模式。优点
无论是对象适配器模式还是类适配器模式都具有如下优点:1.将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
2.增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
3.灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
4.由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
5.一个对象适配器可以把多个不同的适配者适配到同一个目标。
6.可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据“里氏代换原则”,适配者的子类也可通过该适配器进行适配。
缺点
1.对于Java不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者;2.适配者类不能为最终类,如在Java中不能为final类;
3.在Java语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性;
4.与类适配器模式相比,要在适配器中置换适配者类的某些方法比较麻烦。如果一定要置换掉适配者类的一个或多个方法,可以先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
适用场景
1.系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。2.想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
相关文章推荐
- java 中的设计模式---适配器模式
- 设计模式(结构型)之适配器模式(Adapter Pattern)
- 设计模式 适配器模式
- 菜鸟版JAVA设计模式—适配器模式,装饰模式,代理模式异同
- 将设计模式运用于游戏设计:适配器模式
- Java设计模式知识学习-----适配器模式
- 代码设计模式之适配器模式(Adapter)
- 【软考学习】设计模式——适配器模式
- 设计模式之适配器模式
- JAVA设计模式初探之适配器模式
- java设计模式---适配器模式(Adapter pattern)
- PHP 设计模式之适配器模式
- 设计模式实践(五)适配器模式(adapter)
- 【设计模式】适配器模式与Reader、InputStream之间的适配
- [设计模式]适配器模式
- 学习php设计模式 php实现适配器模式
- 设计模式总结篇系列:适配器模式(Adapter)
- 设计模式笔记之适配器模式
- 设计模式(二) 三种适配器模式 总结和使用场景
- 设计模式笔记六:适配器模式