一,适配器模式的定义
适配器模式定义如下:
将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作。适配器模式又叫变压器模式,也叫作包装模式。
A,B两个图框已经塑模成型的物体A和物体B,那现在要求把A和B安装在一起使用,如何安装?两者的接口不一致,是不能安装在一起使用的,那怎么办?引入一个物体C,如图19-6所示。
引入物体C后,C适应了物体A的接口,同时也适应了物体B的接口,然后三者就可以组合成一个完整的物体,如图19-7所示。
其中的物体C就是我们说的适配器,它在中间起到了角色转换的作用,把原有的长条形接口转换了三角形接口。在我们软件业的设计模式中,适配器模式也是相似的功能,那我们先看看适配器模式的三个角色。
-
Target目标角色
该角色定义把其他类转化为何种接口,也就是我们的期待接口。代码如下:
package cn.edu.njtech.book.adapter; public interface Target { // 目标角色自己的方法 public void request(); }package cn.edu.njtech.book.adapter; public class ConcreteTarget implements Target { @Override public void request() { System.out.println("if you need any help,pls call me!"); } } -
Adaptee源角色
你想把谁转换成目标角色,这个"谁"就是源角色,它是已经存在的,运行良好的类或对象,经过适配器角色的包装,它会变成一个崭新的,靓丽的角色。代码如下:
package cn.edu.njtech.book.adapter; public class Adaptee { // 原有的业务逻辑 public void doSomething() { System.out.println("I'am kind of busy,leave me alone,pls!"); } } -
Adapter适配器角色
适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:把源角色转化为目标角色,怎么转换?通过继承或是类关联的方式。
package cn.edu.njtech.book.adapter; public class Adapter extends Adaptee implements Target { @Override public void request() { super.doSomething(); } } -
所有的角色都已经在场了,那我们就开始看看这场演出,场景类代码如下:
package cn.edu.njtech.book.adapter; public class ClientTwo { public static void main(String[] args) { // 原有的业务逻辑 Target target = new ConcreteTarget(); target.request(); // 现在增加了适配器角色后的业务逻辑 Target target1 = new Adapter(); target1.request(); } }
二,通过继承实现适配
假如我们公司原始的员工信息功能完备,这个时候从外面公司借一部分员工过来,别的公司的员工信息接口和我们公司的接口互不兼容,这个时候,适配器的角色可以上战场了。
-
IUserInfo
package cn.edu.njtech.book.adapter; public interface IUserInfo { public String getUserName(); public String getHomeAddress(); public String getMobileNumber(); public String getOfficeTelNumber(); public String getJobPosition(); public String getHomeTelNumber(); } -
UserInfo
package cn.edu.njtech.book.adapter; 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("这个人的手机号是0000..."); return null; } @Override public String getOfficeTelNumber() { System.out.println("办公室电话是..."); return null; } @Override public String getJobPosition() { System.out.println("这个人的职位是BOSS..."); return null; } @Override public String getHomeTelNumber() { System.out.println("员工的家庭电话是..."); return null; } } -
IOuterInfo
package cn.edu.njtech.book.adapter; import java.util.Map; public interface IOuterUser { public Map getUserBaseInfo(); public Map getUserOfficeInfo(); public Map getUserHomeInfo(); } -
OuterUser
package cn.edu.njtech.book.adapter; import java.util.HashMap; import java.util.Map; public class OuterUser implements IOuterUser { @Override public Map getUserBaseInfo() { HashMap baseInfoMap = new HashMap(); baseInfoMap.put("userName", "这个员工叫混世魔王..."); baseInfoMap.put("mobileNumber", "这个员工电话是..."); return baseInfoMap; } @Override public Map getUserOfficeInfo() { HashMap officeInfo = new HashMap(); officeInfo.put("jobPosition", "这个人的职位是BOSS..."); officeInfo.put("officeTelNumber", "员工的办公电话是..."); return officeInfo; } @Override public Map getUserHomeInfo() { HashMap homeInfo = new HashMap(); homeInfo.put("homeTelNumber", "员工的家庭电话是..."); homeInfo.put("homeAddress", "员工的家庭住址是..."); return homeInfo; } } -
适配器类
package cn.edu.njtech.book.adapter; import java.util.Map; public class OuterUserInfoOne extends OuterUser implements IUserInfo { private Map baseInfo = super.getUserBaseInfo(); private Map homeInfo = super.getUserHomeInfo(); private Map officeInfo = super.getUserOfficeInfo(); @Override public String getUserName() { String userName = (String) this.baseInfo.get("userName"); System.out.println(userName); return userName; } @Override public String getHomeAddress() { String homeAddress = (String) this.homeInfo.get("homeAddress"); System.out.println(homeAddress); return homeAddress; } @Override public String getMobileNumber() { String mobileNumber = (String) this.baseInfo.get("mobileNumber"); System.out.println(mobileNumber); return mobileNumber; } @Override public String getOfficeTelNumber() { String officeTelNumber = (String) this.officeInfo.get("officeTelNumber"); System.out.println(officeTelNumber); return officeTelNumber; } @Override public String getJobPosition() { String jobPosition = (String) this.officeInfo.get("jobPosition"); System.out.println(jobPosition); return jobPosition; } @Override public String getHomeTelNumber() { String homeTelNumber = (String) this.homeInfo.get("homeTelNumber"); System.out.println(homeTelNumber); return homeTelNumber; } } -
场景类
package cn.edu.njtech.book.adapter; public class ClientOne { public static void main(String[] args) { IUserInfo youngGirl = new UserInfo(); for (int i = 0; i < 101; i++) { youngGirl.getMobileNumber(); } IUserInfo youngGirlOuter = new OuterUserInfoOne(); for (int i = 0; i < 101; i++) { youngGirlOuter.getMobileNumber(); } } }
三,类关联方式实现适配
Java是单继承的,如果我们的源角色分了三个类,每个类分别实现了三个接口。可以使用类关联的方法,声明一个OuterUserInfo实现类,实现了IUserInfo接口,通过再关联其他三个类就可以解决这个问题了。
-
用户基本信息接口
package cn.edu.njtech.book.adapter; import java.util.Map; public interface IOuterUserBaseInfo { public Map getUserBaseInfo(); } -
用户家庭信息接口
package cn.edu.njtech.book.adapter; import java.util.Map; public interface IOuterUserHomeInfo { public Map getUserHomeInfo(); } -
用户工作信息接口
package cn.edu.njtech.book.adapter; import java.util.Map; public interface IOuterUserOfficeInfo { public Map getUserOfficeInfo(); } -
用户基本信息
package cn.edu.njtech.book.adapter; import java.util.HashMap; import java.util.Map; public class OuterUserBaseInfo implements IOuterUserBaseInfo { @Override public Map getUserBaseInfo() { HashMap baseInfoMap = new HashMap(); baseInfoMap.put("userName", "这个员工叫混世魔王..."); baseInfoMap.put("mobileNumber", "这个员工电话是..."); return baseInfoMap; } } -
用户家庭信息
package cn.edu.njtech.book.adapter; import java.util.HashMap; import java.util.Map; public class OuterUserHomeInfo implements IOuterUserHomeInfo { @Override public Map getUserHomeInfo() { HashMap homeInfo = new HashMap(); homeInfo.put("homeTelNumber", "员工的家庭电话是..."); homeInfo.put("homeAddress", "员工的家庭住址是..."); return homeInfo; } } -
用户工作信息
package cn.edu.njtech.book.adapter; import java.util.HashMap; import java.util.Map; public class OuterUserOfficeInfo implements IOuterUserOfficeInfo { @Override public Map getUserOfficeInfo() { HashMap officeInfo = new HashMap(); officeInfo.put("jobPosition", "这个人的职位是BOSS..."); officeInfo.put("officeTelNumber", "员工的办公电话是..."); return officeInfo; } } -
适配器
package cn.edu.njtech.book.adapter; import java.util.Map; public class OuterUserInfoTwo implements IUserInfo { private IOuterUserBaseInfo baseInfo = null; private IOuterUserHomeInfo homeInfo = null; private IOuterUserOfficeInfo officeInfo = null; private Map baseMap = null; private Map homeMap = null; private Map officeMap = null; public OuterUserInfoTwo(IOuterUserBaseInfo baseInfo, IOuterUserHomeInfo homeInfo, IOuterUserOfficeInfo officeInfo) { this.baseInfo = baseInfo; this.homeInfo = homeInfo; this.officeInfo = officeInfo; this.baseMap = this.baseInfo.getUserBaseInfo(); this.homeMap = this.homeInfo.getUserHomeInfo(); this.officeMap = this.officeInfo.getUserOfficeInfo(); } @Override public String getUserName() { String userName = (String) this.baseMap.get("userName"); System.out.println(userName); return userName; } @Override public String getHomeAddress() { String homeAddress = (String) this.homeMap.get("homeAddress"); System.out.println(homeAddress); return homeAddress; } @Override public String getMobileNumber() { String mobileNumber = (String) this.baseMap.get("mobileNumber"); System.out.println(mobileNumber); return mobileNumber; } @Override public String getOfficeTelNumber() { String officeTelNumber = (String) this.officeMap.get("officeTelNumber"); System.out.println(officeTelNumber); return officeTelNumber; } @Override public String getJobPosition() { String jobPosition = (String) this.officeMap.get("jobPosition"); System.out.println(jobPosition); return jobPosition; } @Override public String getHomeTelNumber() { String homeTelNumber = (String) this.homeMap.get("homeTelNumber"); System.out.println(homeTelNumber); return homeTelNumber; } } -
场景类
package cn.edu.njtech.book.adapter; public class ClientThree { public static void main(String[] args) { IOuterUserBaseInfo baseInfo = new OuterUserBaseInfo(); IOuterUserHomeInfo homeInfo = new OuterUserHomeInfo(); IOuterUserOfficeInfo officeInfo = new OuterUserOfficeInfo(); IUserInfo youngGirl = new OuterUserInfoTwo(baseInfo, homeInfo, officeInfo); for (int i = 0; i < 101; i++) { youngGirl.getMobileNumber(); } } }
四,适配器模式的优点
- 适配器可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成。
- 增加了类的透明性。
- 提高了类的复用度
- 灵活性非常好。
五,写在最后
适配器模式最好在详细设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,没有一个系统分析师会在做详细设计的时候考虑使用适配器模式,这个模式使用的主要场景是扩展应用中。