在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
具体使用场景如下:
若在一个人力资源管理系统中,有人员的录入模块,刚刚开始时,人员信息管理的对象是所有员工的所有信息,也就是说:有一个对象 UserInfo 存储用户的所有信息,示例如下:
项目完成时,需要倒入一批人员数据,例如其他部门的人员数据,但是呢他部门的数据,与此人力资源管理系统不同,主要是表现在员工信息中:
其是把人的信息分为了三部分:基本信息,办公信息和个人家庭信息,并且都放到了 HashMap中,比如人员的姓名放到 BaseInfo信息中,家庭地址放到 HomeInfo 中。
此时录入的时候就是需要使用适配器了,使用适配器模式从而完成人员信息的正确交互和录入,进而尽量少的去动之前的代码。类图如下:
具体代码如下:
1.package mode.test3.impler;
/**
* 用户信息接口类
* @author 张义
*/
public interface IUserInfo {
//获得用户姓名
public String getUserName();
//获得家庭地址
public String getHomeAddress();
//手机号码
public String getMobileNumber();
//办公电话
public String getOfficeTelNumber();
//这个人的职位是啥
public String getJobPosition();
//获得家庭电话
public String getHomeTelNumber();
}
2.实现类
package mode.test3.impl;
import mode.test3.impler.IUserInfo;
public class UserInfo implements IUserInfo {
public String getHomeAddress() {
System.out.println("家庭住址是....");
return null;
}
public String getHomeTelNumber() {
System.out.println("家庭电话是....");
return null;
}
public String getJobPosition() {
System.out.println("员工职位是....");
return null;
}
public String getMobileNumber() {
System.out.println("员工手机是....");
return null;
}
public String getOfficeTelNumber() {
System.out.println("公司电话是....");
return null;
}
public String getUserName() {
System.out.println("员工姓名是....");
return null;
}
}
3.
package mode.test3;
import mode.test3.impl.UserInfo;
import mode.test3.impler.IUserInfo;
/**
* 客户端调用类
* @author 张义
*
*/
public class Client {
public static void main(String[] args) {
IUserInfo userInfo = new UserInfo();
userInfo.getHomeAddress();
userInfo.getHomeTelNumber();
userInfo.getJobPosition();
userInfo.getMobileNumber();
userInfo.getOfficeTelNumber();
userInfo.getUserName();
}
}
若现加上员工的录入信息,如下:
1.
package mode.test3.impler;
import java.util.Map;
/**
* 外来用户信息接口
* @author 张义
*
*/
public interface IOuterUser {
//基本信息,比如名称,性别,手机号码了等
public Map getUserBaseInfo();
//工作区域信息
public Map getUserOfficeInfo();
//用户的家庭信息
public Map getUserHomeInfo();
}
2.
package mode.test3.impl;
import java.util.HashMap;
import java.util.Map;
import mode.test3.impler.IOuterUser;
/**
* 外来用户实现
* @author 张义
*
*/
public class OuterUser implements IOuterUser {
/*
* 员工的家庭信息
*/
public Map getUserHomeInfo() {
HashMap homeInfo = new HashMap();
homeInfo.put("homeTelNumbner", "员工的家庭电话是....");
homeInfo.put("homeAddress", "员工的家庭地址是....");
return homeInfo;
}
/*
* 员工的工作信息,比如职位等
*/
public Map getUserOfficeInfo() {
HashMap officeInfo = new HashMap();
officeInfo.put("jobPosition", "这个人的职位是BOSS...");
officeInfo.put("officeTelNumber", "员工的办公电话是....");
return officeInfo;
}
/*
* 用户的基本信息
*/
public Map getUserBaseInfo() {
HashMap baseInfoMap = new HashMap();
baseInfoMap.put("userName", "这个员工叫混世魔王....");
baseInfoMap.put("mobileNumber", "这个员工电话是....");
return baseInfoMap;
}
}
现需要两模块进行衔接,则需要一适配器模块(继承外来用户类,实现用户类接口),其如下:
package mode.test3;
import java.util.Map;
import mode.test3.impl.OuterUser;
import mode.test3.impler.IUserInfo;
public class OuterUserInfo extends OuterUser implements IUserInfo {
private Map baseInfo = super.getUserBaseInfo(); // 员工的基本信息
private Map homeInfo = super.getUserHomeInfo(); // 员工的家庭 信息
private Map officeInfo = super.getUserOfficeInfo(); // 工作信息
/*
* 家庭地址
*/
public String getHomeAddress() {
String homeAddress = (String) this.homeInfo.get("homeAddress");
System.out.println(homeAddress);
return homeAddress;
}
/*
* 家庭电话号码
*/
public String getHomeTelNumber() {
String homeTelNumber = (String) this.homeInfo.get("homeTelNumber");
System.out.println(homeTelNumber);
return homeTelNumber;
}
/*
* 职位信息
*/
public String getJobPosition() {
String jobPosition = (String) this.officeInfo.get("jobPosition");
System.out.println(jobPosition);
return jobPosition;
}
/*
* 手机号码
*/
public String getMobileNumber() {
String mobileNumber = (String) this.baseInfo.get("mobileNumber");
System.out.println(mobileNumber);
return mobileNumber;
}
/*
* 办公电话
*/
public String getOfficeTelNumber() {
String officeTelNumber = (String) this.officeInfo
.get("officeTelNumber");
System.out.println(officeTelNumber);
return officeTelNumber;
}
/*
* 员工的名称
*/
public String getUserName() {
String userName = (String) this.baseInfo.get("userName");
System.out.println(userName);
return userName;
}
}
最终版客户端:
package mode.test3;
import mode.test3.impl.UserInfo;
import mode.test3.impler.IUserInfo;
/**
* 客户端调用类_最终类
* @author 张义
*
*/
public class Client {
public static void main(String[] args) {
/*IUserInfo userInfo = new UserInfo();*/
// 改正为
IUserInfo userInfo = new OuterUserInfo();
userInfo.getHomeAddress();
userInfo.getHomeTelNumber();
userInfo.getJobPosition();
userInfo.getMobileNumber();
userInfo.getOfficeTelNumber();
userInfo.getUserName();
}
}
总结:
适配器模式不适合在系统设计阶段采用,没有一个系统分析师会在做详设的时候考虑使用适配器模式,这个模式使用的主要场景是扩展应用中,就像我们上面的那个例子一样,系统扩展了,不符合原有设计的时候才考虑通过适配器模式减少代码修改带来的风险。