- 适配器模式:将一个类的接口变成客户端所期待的另一种接口,从而使原本接口不匹配而无法工作的两个类能够在一起工作。
- 适配器模式分为两种,一种是类适配器,一种是对象适配器,其通用类图分别如下:
适配器模式的应用
已知某公司现有一员工管理系统,我们现在从改系统的员工个人信息获取和薪金获取两个模块进行分析,从而解释适配器的两种模式。先来看看系统的员工信息获取的类图:
员工个人信息分为个人基本信息、员工家庭信息、员工公司信息三部分,其源码如下:
public interface IUserBaseInfo { public ArrayList<String> getUserBaseInfo(int userID); } public interface IUserHomeInfo { public ArrayList<String> getUserHomeInfo(int userID); } public interface IUserOfficeInfo { public ArrayList<String> getUserOfficeInfo(int userID); } public class UserBaseInfo implements IUserBaseInfo{ private HashMap<Integer,ArrayList<String>> userBaseInfo = new HashMap<Integer,ArrayList<String>>(); //根据员工ID获取员工个人基本信息(ArrayList中包括员工姓名、手机号) @ Override public ArrayList<String> getUserBaseInfo(int userID) { // TODO Auto-generated method stub ArrayList<String> result = null; iterator iter = userBaseInfo.entrySet().iterator(); while(iter.hasNext()){ Map .Entry entry = (Map.Entry)iter.next(); int id = (int)entry.getKey(); if(id == userID){ result = (ArrayList<String>) entry.getValue(); } } return result; } } public class UserHomeInfo implements IUserHomeInfo{ private HashMap<Integer,ArrayList<String>> userHomeInfo = new HashMap<Integer,ArrayList<String>>(); //根据员工ID获取员工家庭信息(ArrayList中包括家庭住址、家庭电话) @Override public ArrayList<String> getUserHomeInfo(int userID) { // TODO Auto-generated method stub Iterator iter = userHomeInfo.entrySet().iterator(); while(iter.hasNext()){ Map.Entry entry = (Map.Entry)iter.next(); int id = (int)entry.getKey(); if(id == userID){ return (ArrayList<String>) entry.getValue(); } } return null; } } public class UserOfficeInfo implements IUserOfficeInfo{ private HashMap<Integer,ArrayList<String>> userOfficeInfo = new HashMap<Integer,ArrayList<String>>(); //根据员工ID获取员工公司信息(ArrayList中包括员工职位、公司电话) @Override public ArrayList<String> getUserOfficeInfo(int userID) { // TODO Auto-generated method stub Iterator iter = userOfficeInfo.entrySet().iterator(); while(iter.hasNext()){ Map.Entry entry = (Map.Entry)iter.next(); int id = (int)entry.getKey(); if(id == userID){ return (ArrayList<String>)entry.getValue(); } } return null; } }
而另一个系统需要当前系统中的员工信息,而另一个系统中针对员工信息并没有这么细致的分类,而是统称为员工信息,那么该如何很好的实现两个系统的员工信息展示的对接呢,下面我们将利用适配器的对象适配器模式成功实现两个系统的协调工作。首先我们看一下新系统的员工信息类图:
先不说系统设计的好坏,反正系统已经投入运营了,总得实现对接吧,接下来看看新系统的获取员工信息是如何调用原有系统的获取员工信息方法的。
具体的的代码如下:
public interface IUserInfo { public String getUserName(int userID); public String getUserHomeAddress(int userID); public String getMobileNumber(int userID); public String getOfficeTelNumber(int userID); public String getJobPosition(int userID); public String getHomeNumber(int userID); } public class UserInfo implements IUserInfo{ private UserBaseInfo userBaseInfo = new UserBaseInfo(); private UserHomeInfo userHomeInfo = new UserHomeInfo(); private UserOfficeInfo userOfficeInfo = new UserOfficeInfo(); @Override public String getUserName(int userID) { // TODO Auto-generated method stub //0存储员工姓名,1存储员工手机号码 ArrayList<String> userInfo = userBaseInfo.getUserBaseInfo(userID); if(userInfo != null) return userInfo.get(0); return null; } @Override public String getUserHomeAddress(int userID) { // TODO Auto-generated method stub //0存储用户家庭住址,1存储用户家庭电话 ArrayList<String> userInfo = userHomeInfo.getUserHomeInfo(userID); if(userInfo != null) return userInfo.get(0); return null; } @Override public String getMobileNumber(int userID) { // TODO Auto-generated method stub //0存储员工姓名,1存储员工手机号码 ArrayList<String> userInfo = userBaseInfo.getUserBaseInfo(userID); if(userInfo != null) return userInfo.get(1); return null; } @Override public String getOfficeTelNumber(int userID) { // TODO Auto-generated method stub //0存储公司职位,1存储公司电话 ArrayList<String> userInfo = userOfficeInfo.getUserOfficeInfo(userID); if(userInfo != null){ return userInfo.get(1); } return null; } @Override public String getJobPosition(int userID) { // TODO Auto-generated method stub //0存储公司职位,1存储公司电话 ArrayList<String> userInfo = userOfficeInfo.getUserOfficeInfo(userID); if(userInfo != null){ return userInfo.get(0); } return null; } @Override public String getHomeNumber(int userID) { // TODO Auto-generated method stub //0存储用户家庭住址,1存储用户家庭电话 ArrayList<String> userInfo = userHomeInfo.getUserHomeInfo(userID); if(userInfo != null) return userInfo.get(1); return null; } }
仅仅知道个人信息还不满足,又有一个需求是知道每一个人的月薪,这样新系统好发工资啊。那好吧,还是先看看原有的系统是如何实现获取工资的,发现原有的工资的展示是以数组的形式返回的,包括基本工资、奖金、出差费,而新系统我才不管你有什么费用的,我只需要知道一个总的工资,我好发钱就行。那么此时可以用类适配器,其类图如下:
public interface IUserSalary {
public int getSalary(int userID);
}
public class AdapterUserSalary extends UserSalary implements IUserSalary{
@Override
public int getSalary(int userID) {
// TODO Auto-generated method stub
HashMap <String, Integer> salary = (HashMap<String, Integer>) super.getUserSalary(userID);
int userSalary = 0;
Iterator iter = salary.entrySet().iterator();
while(iter.hasNext()){
Map.Entry entry = (Entry) iter.next();
userSalary += (int)entry.getValue();
}
return userSalary;
}
}
适配器模式的优点
- 适配器模式可以让两个没有任何关系的类运行在一起。
- 增加了类的透明性,即高层模块只需知道最后的薪金,并不需要知道薪金具体由哪几部分组成,以及如何获取都不关心。
- 提高了类的复用性,源角色在原有系统中还是可以正常使用,而且可以再新的系统中充当新的角色。
- 灵活性好,突然之间不需要做适配了直接去掉适配器就可以了。