设计模式学习笔记——适配器模式

原文:http://blog.csdn.net/hackerain/article/details/7561138

定义:

将一个类的接口变成客户端所期待的另一种接口,从而使原本因为接口不匹配而无法在一起工作的两个类能够在一起工作


适配器模式有两种表现形式,一种称作“类适配器”,一种称作“对象适配器”。在本文中将举一个“本公司员工和外来公司员工”这样的一个例子,本公司员工的信息是由本公司的系统来维护的,但是外来公司员工的信息是在他们自己的公司中维护的,但是现在要将外来员工的信息整合到本公司的员工管理系统中,但是由于两个公司开发的系统接口并不统一,没办法实现整合,所以用到了适配器的模式,将外来公司的员工的信息类采用适配器模式将其转换成本公司相符合的接口,这样就可以整合了,由于两个公司的实现员工信息的接口,都是使用一个接口来抽象的,所以这里用“类适配器”,就可以了,其类图如下:


实现的源代码如下:

 

[java]   view plain copy
  1. public interface IUserInfo {  
  2.     //个人基本信息  
  3.     public String getUserName();  
  4.     public String getMobileNumber();  
  5.       
  6.     //个人家庭信息  
  7.     public String getHomeAddress();  
  8.     public String getHomeTelNumber();  
  9.       
  10.     //个人公司信息  
  11.     public String getJobPosition();  
  12.     public String getOfficeNumber();  
  13. }  

 

[java]   view plain copy
  1. //这里就是普通的POJO,但是为了模拟,所以这里返回的时候都是返回了一个随机的字符串  
  2.   
  3. public class UserInfo implements IUserInfo {  
  4.       
  5.     @Override  
  6.     public String getUserName() {  
  7.         return Tool.getRandString(5);  
  8.     }  
  9.   
  10.     @Override  
  11.     public String getMobileNumber() {  
  12.         return Tool.getRandNumber(11);  
  13.     }  
  14.   
  15.     @Override  
  16.     public String getHomeAddress() {  
  17.         return Tool.getRandString(10);  
  18.     }  
  19.   
  20.     @Override  
  21.     public String getHomeTelNumber() {  
  22.         return Tool.getRandNumber(11);  
  23.     }  
  24.   
  25.     @Override  
  26.     public String getJobPosition() {  
  27.         return Tool.getRandString(7);  
  28.     }  
  29.   
  30.     @Override  
  31.     public String getOfficeNumber() {  
  32.         return Tool.getRandNumber(11);  
  33.     }  
  34.   
  35. }  

 

[java]   view plain copy
  1. public interface IOuterUserInfo {  
  2.       
  3.     public Map getUserBaseInfo();  
  4.     public Map getUserOfficeInfo();  
  5.     public Map getUserHomeInfo();  
  6. }  

 

[java]   view plain copy
  1. public class OuterUserInfo implements IOuterUserInfo {  
  2.   
  3.     //外来员工的基本信息  
  4.     @SuppressWarnings("rawtypes")  
  5.     @Override  
  6.     public Map getUserBaseInfo() {  
  7.           
  8.         HashMap<String, String> baseInfoMap=new HashMap<String,String>();  
  9.         baseInfoMap.put("username", Tool.getRandString(5));  
  10.         baseInfoMap.put("mobileNumber", Tool.getRandNumber(11));  
  11.           
  12.         return baseInfoMap;  
  13.     }  
  14.   
  15.     //外来员工的公司信息  
  16.     @SuppressWarnings("rawtypes")  
  17.     @Override  
  18.     public Map getUserOfficeInfo() {  
  19.           
  20.         HashMap<String, String> officeInfoMap=new HashMap<String,String>();  
  21.         officeInfoMap.put("jobPosition", Tool.getRandString(7));  
  22.         officeInfoMap.put("officeNumber", Tool.getRandNumber(11));  
  23.           
  24.         return officeInfoMap;  
  25.     }  
  26.   
  27.     //外来员工的家庭信息  
  28.     @SuppressWarnings("rawtypes")  
  29.     @Override  
  30.     public Map getUserHomeInfo() {  
  31.           
  32.         HashMap<String, String> homeInfoMap=new HashMap<String,String>();  
  33.         homeInfoMap.put("homeAddress", Tool.getRandString(10));  
  34.         homeInfoMap.put("homeNumber", Tool.getRandNumber(11));  
  35.           
  36.         return homeInfoMap;  
  37.     }  
  38.   
  39. }  

 

[java]   view plain copy
  1. /* 
  2.  * 类适配器,实现了目标接口的接口,继承了要转换的类 
  3.  */  
  4. public class AdapterOuterUser extends OuterUserInfo implements IUserInfo {  
  5.   
  6.     //从父类获得信息  
  7.     private Map baseInfo=super.getUserBaseInfo();  
  8.     private Map homeInfo=super.getUserHomeInfo();  
  9.     private Map officeInfo=super.getUserOfficeInfo();  
  10.       
  11.     @Override  
  12.     public String getUserName() {  
  13.         return (String)baseInfo.get("username");  
  14.     }  
  15.   
  16.     @Override  
  17.     public String getMobileNumber() {  
  18.         return (String)baseInfo.get("mobileNumber");  
  19.     }  
  20.   
  21.     @Override  
  22.     public String getHomeAddress() {  
  23.         return (String)homeInfo.get("homeAddress");  
  24.     }  
  25.   
  26.     @Override  
  27.     public String getHomeTelNumber() {  
  28.         return (String)homeInfo.get("homeNumber");  
  29.     }  
  30.   
  31.     @Override  
  32.     public String getJobPosition() {  
  33.         return (String)officeInfo.get("jobPosition");  
  34.     }  
  35.   
  36.     @Override  
  37.     public String getOfficeNumber() {  
  38.         return (String)officeInfo.get("officeNumber");  
  39.     }  
  40.   
  41. }  

 

[java]   view plain copy
  1. public class Client {  
  2.     public static void main(String[] args) {  
  3.         //本公司员工信息  
  4.         IUserInfo selfUser=new UserInfo();  
  5.         System.out.println(selfUser.getUserName()+" "+selfUser.getMobileNumber());  
  6.           
  7.         System.out.println();  
  8.           
  9.         //外来员工信息  
  10.         IUserInfo outerUser=new AdapterOuterUser();  
  11.         System.out.println(outerUser.getUserName()+" "+outerUser.getHomeTelNumber());  
  12.     }  
  13. }  


上面讲解的是类适配器,用类适配器的原因在于两个公司的员工信息都是用一个接口抽象的,如果其中一个公司人家员工信息抽象的是好几个接口,比如说上面外来公司如果员工信息抽象了三个接口,那怎么办?尤其是java,java不支持多继承,所以就有了另外一种解决方案:对象适配器,看如下类图:


其实现代码如下(IUserInfo和UserInfo和上面一样,这里就不重复了):

 

[java]   view plain copy
  1. public interface IOuterUserBaseInfo {  
  2.     public Map getUserBaseInfo();  
  3. }  
  4.   
  5. public interface IOuterUserHomeInfo {  
  6.     public Map getUserHomeInfo();  
  7. }  
  8.   
  9. public interface IOuterUserOfficeInfo {  
  10.     public Map getUserOfficeInfo();  
  11. }  

 

[java]   view plain copy
  1. public class OuterUserBaseInfo implements IOuterUserBaseInfo {  
  2.   
  3.     @Override  
  4.     public Map getUserBaseInfo() {  
  5.           
  6.         HashMap<String, String> baseInfoMap=new HashMap<String,String>();  
  7.         baseInfoMap.put("username", Tool.getRandString(5));  
  8.         baseInfoMap.put("mobileNumber", Tool.getRandNumber(11));  
  9.           
  10.         return baseInfoMap;  
  11.     }  
  12.   
  13. }  

 

[java]   view plain copy
  1. public class OuterUserHomeInfo implements IOuterUserHomeInfo {  
  2.   
  3.     @Override  
  4.     public Map getUserHomeInfo() {  
  5.         HashMap<String, String> homeInfoMap=new HashMap<String,String>();  
  6.         homeInfoMap.put("homeAddress", Tool.getRandString(10));  
  7.         homeInfoMap.put("homeNumber", Tool.getRandNumber(11));  
  8.           
  9.         return homeInfoMap;  
  10.     }  
  11.   
  12. }  

 

[java]   view plain copy
  1. public class OuterUserOfficeInfo implements IOuterUserOfficeInfo {  
  2.   
  3.     @Override  
  4.     public Map getUserOfficeInfo() {  
  5.         HashMap<String, String> officeInfoMap=new HashMap<String,String>();  
  6.         officeInfoMap.put("jobPosition", Tool.getRandString(7));  
  7.         officeInfoMap.put("officeNumber", Tool.getRandNumber(11));  
  8.           
  9.         return officeInfoMap;  
  10.     }  
  11.   
  12. }  


 

[java]   view plain copy
  1. /* 
  2.  * 对象适配器,实现了目标接口的接口,并把源目标对象作为成员变量 
  3.  */  
  4. public class AdapterOuterUser implements IUserInfo {  
  5.   
  6.     //源目标对象  
  7.     private IOuterUserBaseInfo baseInfoObj=null;  
  8.     private IOuterUserHomeInfo homeInfoObj=null;  
  9.     private IOuterUserOfficeInfo officeInfoObj=null;  
  10.       
  11.     //数据处理  
  12.     private Map baseInfo=null;  
  13.     private Map homeInfo=null;  
  14.     private Map officeInfo=null;  
  15.       
  16.       
  17.     public AdapterOuterUser(IOuterUserBaseInfo baseInfoObj,  
  18.             IOuterUserHomeInfo homeInfoObj, IOuterUserOfficeInfo officeInfoObj) {  
  19.         this.baseInfoObj = baseInfoObj;  
  20.         this.homeInfoObj = homeInfoObj;  
  21.         this.officeInfoObj = officeInfoObj;  
  22.           
  23.         //数据处理  
  24.         this.baseInfo=baseInfoObj.getUserBaseInfo();  
  25.         this.homeInfo=homeInfoObj.getUserHomeInfo();  
  26.         this.officeInfo=officeInfoObj.getUserOfficeInfo();  
  27.     }  
  28.   
  29.     @Override  
  30.     public String getUserName() {  
  31.         return (String)baseInfo.get("username");  
  32.     }  
  33.   
  34.     @Override  
  35.     public String getMobileNumber() {  
  36.         return (String)baseInfo.get("mobileNumber");  
  37.     }  
  38.   
  39.     @Override  
  40.     public String getHomeAddress() {  
  41.         return (String)homeInfo.get("homeAddress");  
  42.     }  
  43.   
  44.     @Override  
  45.     public String getHomeTelNumber() {  
  46.         return (String)homeInfo.get("homeNumber");  
  47.     }  
  48.   
  49.     @Override  
  50.     public String getJobPosition() {  
  51.         return (String)officeInfo.get("jobPosition");  
  52.     }  
  53.   
  54.     @Override  
  55.     public String getOfficeNumber() {  
  56.         return (String)officeInfo.get("officeNumber");  
  57.     }  
  58.   
  59. }  


 

[java]   view plain copy
  1. public class Client {  
  2.     public static void main(String[] args) {  
  3.         //本公司员工信息  
  4.         IUserInfo selfUser=new UserInfo();  
  5.         System.out.println(selfUser.getUserName()+" "+selfUser.getMobileNumber());  
  6.           
  7.         System.out.println();  
  8.           
  9.         //外来员工信息  
  10.         IOuterUserBaseInfo baseInfo=new OuterUserBaseInfo();  
  11.         IOuterUserHomeInfo homeInfo=new OuterUserHomeInfo();  
  12.         IOuterUserOfficeInfo officeInfo=new OuterUserOfficeInfo();  
  13.           
  14.         IUserInfo outerUser=new AdapterOuterUser(baseInfo,homeInfo,officeInfo);  
  15.         System.out.println(outerUser.getUserName()+" "+outerUser.getHomeTelNumber());  
  16.     }  
  17. }  



适配器模式的优点:

1、适配器可以让两个没有任何关系的类在一起运行。

2、增加了类的透明性

3、提高了类的复用度

4、灵活性非常好,当不想要适配器时,直接删掉就可以了,其他的代码几乎不用修改。


体会:

适配器模式就是在增加或修改一个已经投产中的产品时,若发现新增的类或是从外部导入的类不符合本系统的接口,则可以使用适配器模式解决这个问题,避免了直接修改接口这个高危险的动作。

适配器模式可以发挥它的独特的魅力,其中很重要的一个原因就是原因的系统严格的遵守了依赖倒置原则,即是严格的面向接口编程,才使系统有这么大的“肚量”,这里也很好的体现了依赖倒置原则的重要性。


适配器模式使用场景:


你有动机修改一个已经投产中的接口时,适配器可能是最合适你的模式。比如系统扩展了,需要使用一个已有或新建立的类,但这个类又不符合系统给的接口,使用适配器模式。项目一定要遵守依赖倒置原则和里氏替换原则,否则即使在使用适配器场合下,也会带来非常大的改造。


对象适配器和类适配器的区别:类适配器是类间继承,对象适配器是对象的合成关系,也可以说是类的关联关系。优先使用对象适配器。

适配器模式一个补偿模式,或者说是一个“补救模式”,用来解决接口不相容的问题。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值