1. 定义:
适配器模式的定义是,Convert the interface of a class into another interface clients expect,将某个类的接口转换为接口客户所需的类型。适配器模式解决的问题是,使得原本由于接口不兼容而不能一起工作、不能统一管理的那些类可以在一起工作、可以进行统一管理。将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器。
个人觉得这些定义不太容易理解,但是我找到一句话,觉得更符合我对适配器模式的理解:适配器是为了不改变有的代码实现,但是又要满足现有的需求,更像是属于一种被动选择。
Adapter模式的宗旨:保留现有类所提供的服务,向客户提供接口,以满足客户的期望
2.先举一个例子,现在有一个方法,而这个方法可以产生220V的电压,然后我买了一个手机,手机充电电压是5V,如何用220V的方法给5V的手机充电,同时有又不改变原有的220V电压的方法。那么我就需要一个手机充电器来作为适配,将220V电压,转化为5V的电压,手机充电器就是适配器类。(注意,不要对我举例产生固有思维,举例只是为了形象理解,事实上适配器就是为了:保留现有类所提供的服务,向客户提供接口,以满足客户的期望)
2.1 适配器有类 适配器 和 对象适配器
以上面的例子来实现类适配器代码,先有一个供电站接口,各个地区供电站都可以实现这个接口,提供不同的电压
/**
* 供电站 接口
* @author lx
*
*/
public interface PowerStation {
/**
* 供电接口 返回电压
* @return
*/
public int providePower();
}
2.2.现有亳州供电站为用户提供220V电压供电,具体实现
public class BoZhouPowerStation implements PowerStation{
@Override
public int providePower() {
// 我这里举例比代码较少,一般项目中可能有复杂的业务逻辑
return 220;
}
}
2.3.现在我手机没电了,想要给手机充电,我就多写一个手机充电接口
/**
* 手机充电接口
* @author lx
*
*/
public interface PhoneCharge {
public String chargePower();
}
2.4.我要给我的华为手机充电,华为手机实现手机充电接口,具有充电的能力,但是需要5V电压进行充电,但是我们只有220V电压的实现类,当电压实现类是比较复杂的,就像亳州供电站一样,不可能为了手机充电,提供一个5V电压供电站。(如果在代码中,类似于电压实现类比较简单,也可以实现供电站接口,提供一个5V的电压 ,直接调用即可)
public class HuaWeiPhone implements PhoneCharge{
//需要5V电压进行充电
@Override
public String chargePower() {
return null;
}
}
现在需要对上述代码进行改造,保持原有220V电压实现类不变,因为可能有其它地方调用,改造后的代码
public class HuaWeiPhone extends BoZhouPowerStation implements PhoneCharge{
@Override
public String chargePower() {
//获取220v电压操作
int voltage = this.providePower();
//将电压转化为5v操作
int phoneVoltage = voltage/44;
System.out.println("通过亳州供电站为华为手机充电,电压:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
}
我们new 一个华为手机对象,执行上述方法,即可为华为手机充电。上述通过继承实现两个接口的连接,即为类适配器模式,这种模式的缺点会增加代码的耦合性,不太灵活。
3.对象适配器模式 代码 现在我使用小米手机,充电需要10V电压
public class XiaoMiPhone implements PhoneCharge{
public BoZhouPowerStation bzs;
public XiaoMiPhone() {
bzs = new BoZhouPowerStation();
}
@Override
public String chargePower() {
//获取220v电压操作
int voltage = bzs.providePower();
//将电压转化为10v操作
int phoneVoltage = voltage/22;
System.out.println("同过亳州供电站获取手机充电电压:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
4. 上述实现方式不太好的地方在与,我的小米手机只能使用亳州供电站,并且这个亳州供电站还是小米充电器自带的。还是不够灵活,修改为如下:
public class XiaoMiPhone implements PhoneCharge{
public BoZhouPowerStation bzs;
public XiaoMiPhone(BoZhouPowerStation bzs) {
this.bzs = bzs;
}
@Override
public String chargePower() {
//获取220v电压操作
int voltage = bzs.providePower();
//将电压转化为10v操作
int phoneVoltage = voltage/22;
System.out.println("同过亳州供电站获取手机充电电压:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
}
5.上述代码,也不够灵活,虽然亳州供电站不用在代码内部创建了,但是我出差到上海想使用上供电站的电对我的手机进行充电,需要做如下修改:
public class XiaoMiPhone implements PhoneCharge{
public PowerStation ps;
public XiaoMiPhone(PowerStation ps) {
this.ps = ps;
}
@Override
public String chargePower() {
//获取220v电压操作
int voltage = ps.providePower();
//将电压转化为10v操作
int phoneVoltage = voltage/22;
System.out.println("同过亳州供电站获取手机充电电压:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
}
6.适配器模式的使用场景
(1)其中一个使用的场景是像上面所说的一样,有两个接口,你主动的想去连接着两个接口,写个适配器,感觉这种情况也不是很多,因为很多时候都是些一个实体类对象调用另一个实体类对象。
(2)被动使用的情况比较多。举个栗子,你开发新版本的时候重新定义了接口,要和旧版本写适配的时候,为了方便也可以使用适配器模式。