设计模式学习笔记——适配器模式
来源:互联网 发布:nokia windows phone 编辑:程序博客网 时间:2024/06/05 14:16
原文:http://blog.csdn.net/hackerain/article/details/7561138
定义:
将一个类的接口变成客户端所期待的另一种接口,从而使原本因为接口不匹配而无法在一起工作的两个类能够在一起工作。
适配器模式有两种表现形式,一种称作“类适配器”,一种称作“对象适配器”。在本文中将举一个“本公司员工和外来公司员工”这样的一个例子,本公司员工的信息是由本公司的系统来维护的,但是外来公司员工的信息是在他们自己的公司中维护的,但是现在要将外来员工的信息整合到本公司的员工管理系统中,但是由于两个公司开发的系统接口并不统一,没办法实现整合,所以用到了适配器的模式,将外来公司的员工的信息类采用适配器模式将其转换成本公司相符合的接口,这样就可以整合了,由于两个公司的实现员工信息的接口,都是使用一个接口来抽象的,所以这里用“类适配器”,就可以了,其类图如下:
实现的源代码如下:
- public interface IUserInfo {
- //个人基本信息
- public String getUserName();
- public String getMobileNumber();
- //个人家庭信息
- public String getHomeAddress();
- public String getHomeTelNumber();
- //个人公司信息
- public String getJobPosition();
- public String getOfficeNumber();
- }
- //这里就是普通的POJO,但是为了模拟,所以这里返回的时候都是返回了一个随机的字符串
- public class UserInfo implements IUserInfo {
- @Override
- public String getUserName() {
- return Tool.getRandString(5);
- }
- @Override
- public String getMobileNumber() {
- return Tool.getRandNumber(11);
- }
- @Override
- public String getHomeAddress() {
- return Tool.getRandString(10);
- }
- @Override
- public String getHomeTelNumber() {
- return Tool.getRandNumber(11);
- }
- @Override
- public String getJobPosition() {
- return Tool.getRandString(7);
- }
- @Override
- public String getOfficeNumber() {
- return Tool.getRandNumber(11);
- }
- }
- public interface IOuterUserInfo {
- public Map getUserBaseInfo();
- public Map getUserOfficeInfo();
- public Map getUserHomeInfo();
- }
- public class OuterUserInfo implements IOuterUserInfo {
- //外来员工的基本信息
- @SuppressWarnings("rawtypes")
- @Override
- public Map getUserBaseInfo() {
- HashMap<String, String> baseInfoMap=new HashMap<String,String>();
- baseInfoMap.put("username", Tool.getRandString(5));
- baseInfoMap.put("mobileNumber", Tool.getRandNumber(11));
- return baseInfoMap;
- }
- //外来员工的公司信息
- @SuppressWarnings("rawtypes")
- @Override
- public Map getUserOfficeInfo() {
- HashMap<String, String> officeInfoMap=new HashMap<String,String>();
- officeInfoMap.put("jobPosition", Tool.getRandString(7));
- officeInfoMap.put("officeNumber", Tool.getRandNumber(11));
- return officeInfoMap;
- }
- //外来员工的家庭信息
- @SuppressWarnings("rawtypes")
- @Override
- public Map getUserHomeInfo() {
- HashMap<String, String> homeInfoMap=new HashMap<String,String>();
- homeInfoMap.put("homeAddress", Tool.getRandString(10));
- homeInfoMap.put("homeNumber", Tool.getRandNumber(11));
- return homeInfoMap;
- }
- }
- /*
- * 类适配器,实现了目标接口的接口,继承了要转换的类
- */
- public class AdapterOuterUser extends OuterUserInfo implements IUserInfo {
- //从父类获得信息
- private Map baseInfo=super.getUserBaseInfo();
- private Map homeInfo=super.getUserHomeInfo();
- private Map officeInfo=super.getUserOfficeInfo();
- @Override
- public String getUserName() {
- return (String)baseInfo.get("username");
- }
- @Override
- public String getMobileNumber() {
- return (String)baseInfo.get("mobileNumber");
- }
- @Override
- public String getHomeAddress() {
- return (String)homeInfo.get("homeAddress");
- }
- @Override
- public String getHomeTelNumber() {
- return (String)homeInfo.get("homeNumber");
- }
- @Override
- public String getJobPosition() {
- return (String)officeInfo.get("jobPosition");
- }
- @Override
- public String getOfficeNumber() {
- return (String)officeInfo.get("officeNumber");
- }
- }
- public class Client {
- public static void main(String[] args) {
- //本公司员工信息
- IUserInfo selfUser=new UserInfo();
- System.out.println(selfUser.getUserName()+" "+selfUser.getMobileNumber());
- System.out.println();
- //外来员工信息
- IUserInfo outerUser=new AdapterOuterUser();
- System.out.println(outerUser.getUserName()+" "+outerUser.getHomeTelNumber());
- }
- }
上面讲解的是类适配器,用类适配器的原因在于两个公司的员工信息都是用一个接口抽象的,如果其中一个公司人家员工信息抽象的是好几个接口,比如说上面外来公司如果员工信息抽象了三个接口,那怎么办?尤其是java,java不支持多继承,所以就有了另外一种解决方案:对象适配器,看如下类图:
其实现代码如下(IUserInfo和UserInfo和上面一样,这里就不重复了):
- public interface IOuterUserBaseInfo {
- public Map getUserBaseInfo();
- }
- public interface IOuterUserHomeInfo {
- public Map getUserHomeInfo();
- }
- public interface IOuterUserOfficeInfo {
- public Map getUserOfficeInfo();
- }
- public class OuterUserBaseInfo implements IOuterUserBaseInfo {
- @Override
- public Map getUserBaseInfo() {
- HashMap<String, String> baseInfoMap=new HashMap<String,String>();
- baseInfoMap.put("username", Tool.getRandString(5));
- baseInfoMap.put("mobileNumber", Tool.getRandNumber(11));
- return baseInfoMap;
- }
- }
- public class OuterUserHomeInfo implements IOuterUserHomeInfo {
- @Override
- public Map getUserHomeInfo() {
- HashMap<String, String> homeInfoMap=new HashMap<String,String>();
- homeInfoMap.put("homeAddress", Tool.getRandString(10));
- homeInfoMap.put("homeNumber", Tool.getRandNumber(11));
- return homeInfoMap;
- }
- }
- public class OuterUserOfficeInfo implements IOuterUserOfficeInfo {
- @Override
- public Map getUserOfficeInfo() {
- HashMap<String, String> officeInfoMap=new HashMap<String,String>();
- officeInfoMap.put("jobPosition", Tool.getRandString(7));
- officeInfoMap.put("officeNumber", Tool.getRandNumber(11));
- return officeInfoMap;
- }
- }
- /*
- * 对象适配器,实现了目标接口的接口,并把源目标对象作为成员变量
- */
- public class AdapterOuterUser implements IUserInfo {
- //源目标对象
- private IOuterUserBaseInfo baseInfoObj=null;
- private IOuterUserHomeInfo homeInfoObj=null;
- private IOuterUserOfficeInfo officeInfoObj=null;
- //数据处理
- private Map baseInfo=null;
- private Map homeInfo=null;
- private Map officeInfo=null;
- public AdapterOuterUser(IOuterUserBaseInfo baseInfoObj,
- IOuterUserHomeInfo homeInfoObj, IOuterUserOfficeInfo officeInfoObj) {
- this.baseInfoObj = baseInfoObj;
- this.homeInfoObj = homeInfoObj;
- this.officeInfoObj = officeInfoObj;
- //数据处理
- this.baseInfo=baseInfoObj.getUserBaseInfo();
- this.homeInfo=homeInfoObj.getUserHomeInfo();
- this.officeInfo=officeInfoObj.getUserOfficeInfo();
- }
- @Override
- public String getUserName() {
- return (String)baseInfo.get("username");
- }
- @Override
- public String getMobileNumber() {
- return (String)baseInfo.get("mobileNumber");
- }
- @Override
- public String getHomeAddress() {
- return (String)homeInfo.get("homeAddress");
- }
- @Override
- public String getHomeTelNumber() {
- return (String)homeInfo.get("homeNumber");
- }
- @Override
- public String getJobPosition() {
- return (String)officeInfo.get("jobPosition");
- }
- @Override
- public String getOfficeNumber() {
- return (String)officeInfo.get("officeNumber");
- }
- }
- public class Client {
- public static void main(String[] args) {
- //本公司员工信息
- IUserInfo selfUser=new UserInfo();
- System.out.println(selfUser.getUserName()+" "+selfUser.getMobileNumber());
- System.out.println();
- //外来员工信息
- IOuterUserBaseInfo baseInfo=new OuterUserBaseInfo();
- IOuterUserHomeInfo homeInfo=new OuterUserHomeInfo();
- IOuterUserOfficeInfo officeInfo=new OuterUserOfficeInfo();
- IUserInfo outerUser=new AdapterOuterUser(baseInfo,homeInfo,officeInfo);
- System.out.println(outerUser.getUserName()+" "+outerUser.getHomeTelNumber());
- }
- }
适配器模式的优点:
1、适配器可以让两个没有任何关系的类在一起运行。
2、增加了类的透明性
3、提高了类的复用度
4、灵活性非常好,当不想要适配器时,直接删掉就可以了,其他的代码几乎不用修改。
体会:
适配器模式就是在增加或修改一个已经投产中的产品时,若发现新增的类或是从外部导入的类不符合本系统的接口,则可以使用适配器模式解决这个问题,避免了直接修改接口这个高危险的动作。
适配器模式可以发挥它的独特的魅力,其中很重要的一个原因就是原因的系统严格的遵守了依赖倒置原则,即是严格的面向接口编程,才使系统有这么大的“肚量”,这里也很好的体现了依赖倒置原则的重要性。
适配器模式使用场景:
你有动机修改一个已经投产中的接口时,适配器可能是最合适你的模式。比如系统扩展了,需要使用一个已有或新建立的类,但这个类又不符合系统给的接口,使用适配器模式。项目一定要遵守依赖倒置原则和里氏替换原则,否则即使在使用适配器场合下,也会带来非常大的改造。
对象适配器和类适配器的区别:类适配器是类间继承,对象适配器是对象的合成关系,也可以说是类的关联关系。优先使用对象适配器。
适配器模式一个补偿模式,或者说是一个“补救模式”,用来解决接口不相容的问题。
- 设计模式学习笔记——适配器模式
- 设计模式学习笔记——适配器模式
- 设计模式学习笔记——适配器模式
- 设计模式学习笔记——适配器模式
- Head First 设计模式学习笔记 —— 适配器模式
- 设计模式学习笔记——适配器(Adapter)模式
- 学习笔记——JAVA设计模式<5>适配器模式
- 十三、适配器模式——设计模式学习笔记
- 设计模式学习笔记(二)—-Adapter适配器模式
- 设计模式笔记——适配器模式
- Java设计模式学习—适配器模式
- PHP设计模式——适配器模式(研磨设计模式学习笔记)
- 设计模式学习笔记之适配器模式
- 设计模式学习笔记-适配器模式
- java设计模式学习笔记-适配器模式
- 设计模式学习笔记--适配器(Adapter)模式
- 设计模式学习笔记-适配器模式
- 设计模式学习笔记-适配器模式
- 获取手机信息
- xlwt 里easyxf能理解的颜色预览
- 关于调整input里面的输入光标大小
- WP-Polls简体中文语言包(根据官方语言包修改完善)
- 9i Oracle中模拟及修复数据块损坏
- 设计模式学习笔记——适配器模式
- 数据挖掘 预测
- 从加载单个xib到加载storyboard中的单个controller的转变
- ace 半包和粘包问题的解决
- Android 关于资源适配
- oracle中的exists 和not exists 用法
- Windows安装Maven
- 软件学习计划
- Eclipse 常用快捷键