笔记本上拖在外面的黑盒子就是个适配器,适配器能够把这些不同的电压转换为你需要的36V电压,保证你的笔记本能够正常运行,
两个不同的接口,有不同的实现,但是某一天突然上帝命令你把B接口转换为A接口,怎么办?继承,能解决问题,但是比较傻,而且违背OCP原则,怎么办?好在我们有适配器模式。
其他:在一个对象中不存储实体状态以及对象之间的关系的就叫做贫血对象,上升到领域模型中就是贫血领域模型,有实体状态和对象关系的模型的就是充血领域模型。
背景:做一个人力资源管理系统,分为三大模块:人员信息管理,薪酬管理,职位管理,其中人员管理这块,在于其他系统交互时,就用到了适配器模式。人员信息管理的对象是所有员工的所有信息。
人力资源公司的人员管理系统中的人员对象和我们系统的对象不相同,咱的系统要和他们的系统有交互,就要使用适配器模式。
两个对象都不在一个系统中,如何使用?RMI已经帮我们做了这件事,只要有接口,就可以把远程的对象当成本地的对象使用,这个大家有时间可以查看RMI文档。
通过适配器,把OuterUser伪装成我们系统中一个IUserInfo对象,这样,我们的系统基本不用修改什么程序,所有人员查询、调用跟本地一样。
首先,定义本地对象接口:
package com.teng.pattern.inter;
/**
* 本地用户信息对象
* <br>创建日期:2016年6月30日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public interface IUserInfo {
/**
* 用户姓名
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:13:18
*/
public String getUserName();
/**
* 家庭住址
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:14:21
*/
public String getHomeAddress();
/**
* 手机号码
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:14:54
*/
public String getMobileNumber();
/**
* 办公电话
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:16:49
*/
public String getOfficeTelNumber();
/**
* 职位
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:18:30
*/
public String getJobPosition();
/**
* 家庭电话
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:19:17
*/
public String getHomeTelNumber();
}
本地对象接口的实现类:
package com.teng.pattern.impl;
import com.teng.pattern.inter.IUserInfo;
/**
* 本地用户信息对象实现
* <br>创建日期:2016年6月30日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class UserInfo implements IUserInfo {
@Override
public String getUserName() {
System.out.println("姓名。。。。。。");
return null;
}
@Override
public String getHomeAddress() {
System.out.println("家庭住址。。。。。。");
return null;
}
@Override
public String getMobileNumber() {
System.out.println("手机号码。。。。。。");
return null;
}
@Override
public String getOfficeTelNumber() {
System.out.println("办公室电话号码。。。。。。");
return null;
}
@Override
public String getJobPosition() {
System.out.println("职位。。。。。。");
return null;
}
@Override
public String getHomeTelNumber() {
System.out.println("家庭电话。。。。。。");
return null;
}
}
外部对象接口:
package com.teng.pattern.inter;
import java.util.Map;
/**
* 外部系统用户信息实体
* <br>创建日期:2016年6月30日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public interface IOuterUser {
/**
* 基本信息,比如名称、性别、手机号
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:32:18
*/
public Map getUserBaseInfo();
/**
* 工作区域信息
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:33:34
*/
public Map getUserOfficeInfo();
/**
* 用户的家庭信息
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:34:32
*/
public Map getUserHomeInfo();
}
外部对象接口的实现:
package com.teng.pattern.impl;
import java.util.HashMap;
import java.util.Map;
import com.teng.pattern.inter.IOuterUser;
/**
* 外部系统用户信息对象
* <br>创建日期:2016年6月30日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class OuterUser implements IOuterUser {
@Override
public Map getUserBaseInfo() {
Map<String,String> baseInfoMap = new HashMap<String,String>();
baseInfoMap.put("userName", "M:姓名小刚。。。。。。");
baseInfoMap.put("mobileNumber", "M:员工电话。。。。。。");
return baseInfoMap;
}
@Override
public Map getUserOfficeInfo() {
Map<String,String> officeInfoMap = new HashMap<String,String>();
officeInfoMap.put("jobPosition", "M:职位信息。。。。。。");
officeInfoMap.put("officeTelNumber", "M:办公电话。。。。。。");
return officeInfoMap;
}
@Override
public Map getUserHomeInfo() {
Map<String,String> homeInfoMap = new HashMap<String,String>();
homeInfoMap.put("homeTelNumber", "M:家庭电话。。。。。。");
homeInfoMap.put("homeAddress", "M:家庭住址。。。。。。");
return homeInfoMap;
}
}
电话号码、手机号码都设置成String类型,数据库也应该是varchar类型。
适配器类:
package com.teng.pattern.impl;
import java.util.Map;
import com.teng.pattern.inter.IUserInfo;
/**
* 适配器类,外系统对象 向 本地系统对象转换
* <br>创建日期:2016年6月30日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class OuterUserInfo extends OuterUser implements IUserInfo {
private Map<String,String> baseInfo = super.getUserBaseInfo();
private Map<String,String> officeInfo = super.getUserOfficeInfo();
private Map<String,String> homeInfo = super.getUserHomeInfo();
@Override
public String getUserName() {
System.out.println(baseInfo.get("userName"));
return null;
}
@Override
public String getHomeAddress() {
System.out.println(homeInfo.get("homeAddress"));
return null;
}
@Override
public String getMobileNumber() {
System.out.println(baseInfo.get("mobileNumber"));
return null;
}
@Override
public String getOfficeTelNumber() {
System.out.println(officeInfo.get("officeTelNumber"));
return null;
}
@Override
public String getJobPosition() {
System.out.println(officeInfo.get("jobPosition"));
return null;
}
@Override
public String getHomeTelNumber() {
System.out.println(homeInfo.get("homeTelNumber"));
return null;
}
}
适配器的作用就是做接口的转换。
应用:
package com.teng.pattern.impl;
import com.teng.pattern.inter.IUserInfo;
/**
* 系统调用
* <br>创建日期:2016年6月30日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class App {
/**
* 主方法
* @since 1.0
* @param args
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月30日 下午8:26:33
*/
public static void main(String[] args) {
//IUserInfo youngGirl = new UserInfo();
IUserInfo youngGirl = new OuterUserInfo();
for(int i = 0;i < 101 ;i++){
System.out.println(i+" "+youngGirl.getMobileNumber());
}
}
}
使用了适配器模式只修改了一句话,其他的业务逻辑都不用修改就解决了系统对接的问题,而且在我们实际系统中只增加了一个业务类的继承,就实现了可以查本公司的员工信息,也可以查人力资源公司的员工信息。
适配器模式分为类适配器和对象适配器,上例就是类适配器,它们的差异就是,一个是继承,一个是关联。
适配器模式不适合在系统设计阶段采用,没有一个系统分析师会在做详细设计的时候考虑使用适配器模式,这个模式使用的主要场景是扩展应用中。