1. 定义和结构图
适配器模式的定义:
- 将一个类的接口转成客户期望的另外一个接口,适配器模式使得原本由于接口不匹配而不能一起工作的那些类可以一起工作;
适配器模式的结构图:
如图所示:
- Client不能直接访问Adapter;
- Adapter是适配器,它将Adaptee转换成Client能访问的接口,所以通过适配器Adapter,用户端就可以访问Adaptee;
2. 栗子
下面通过一个栗子来实现一个适配器:
1. Java中的适配器
在Java中,适配器可以应用在很多场景中,最常见的比如我们老接口改造,但是要让它不影响旧版本项目的使用,这个时候我们就可以使用适配器模式,使新版本项目和旧版本项目都可以兼容;
适配器模式一共有三个角色:
- 目标角色
- 适配器角色
- 源角色
其过程就是通过适配器将源角色API进行适配为目标角色的API;
2. 三种适配器模式(⭐)
以手机充电器适配器为例,目前市场上大多数适配器都是将220V电压进行适配为5V电压供手机使用,我们就以这个为例来实现三种适配器;
1. 类适配器模式
类适配器模式是通过继承来实现适配器模式的;
先定义一个源角色(即220V电压):
class AC220V{
public int output220V() {
int output220v = 220;
return output220v;
}
}
再定义一个目标角色(即从适配器获取到5V电压),这是一个接口,是用户期待的接口:
interface DC5V {
int dc5V();
}
接下来实现我们的适配器:
class Adapter extends AC220V implements DC5V {
@Override
public int dc5V() {
//调用父类的那个方法获取到源角色,然后进行改造;
int output220V = output220V();
int output5V = output220V / 44;
return output5V;
}
}
现在编写一个测试类来检测:
public class Test2 {
public static void main(String[] args) {
DC5V dc5V = new Adapter();
int dc5 = dc5V.dc5V();
System.out.println("转换后的电压为:"+dc5);
}
}
转换后的电压为:5
2. 对象适配器
对象适配器是通过组合的方式来实现适配功能的,即适配器拥有源角色的实例,我们使用代码来看看:
源角色和目标角色跟上面是一模一样的,就适配器做了点改变,适配器代码如下:
class Adapter implements DC5V {
private AC220V ac220V;
public Adapter(AC220V ac220V) {
this.ac220V = ac220V;
}
@Override
public int dc5V() {
int output220V = ac220V.output220V();
return (output220V / 44);
}
}
测试:
public class Test2 {
public static void main(String[] args) {
//需要传入源角色的实例哦
DC5V dc5V = new Adapter(new AC220V());
int dc5 = dc5V.dc5V();
System.out.println("转换后的电压为:"+dc5);
}
}
输出:
转换后的电压为:5
3. 接口适配器
相对于上面的类适配器和对象适配器来说,接口适配器更加灵活,就好比手机适配器中的万能适配器,能将无论多少伏的电压转换成5V;
下面看代码: 👇👇👇
先定义一个抽象的电源(给予一个默认值220V):
abstract class ACV {
public int output() {
return 220;
}
}
再定义两个具体的电源(220V和110V,这两个类都继承了抽象类电源):
class AC220V extends ACV {
@Override
public int output() {
return 220;
}
}
class AC110V extends ACV {
@Override
public int output() {
return 110;
}
}
上面就定义好了源角色,下面来定义目标角色:
interface DC5V {
int dc5V();
}
现在来定义适配器:
class Adapter implements DC5V {
private ACV acv;
public Adapter(AC220V ac220V) {
this.acv = ac220V;
}
public Adapter(AC110V ac110V) {
this.acv = ac110V;
}
@Override
public int dc5V() {
int ac = 0;
if(acv != null) {
ac = acv.output();
}
int sta = ac / 5;
//这里结果恒为5,这只是个栗子来达到我们的效果,具体怎么处理看场景
return ac / sta;
}
}
如上代码,在适配器角色中,我们定义一个抽象的电源,并且提供多个适配器角色的有参构造,通过具体源角色的实例使用抽象的电源引用,适配器类实现于目标角色并实现目标角色的方法,在方法体中,我们进行逻辑处理,将输入的电压进行适配为5V电压,从而达到万能适配的效果。 这样,不管输入的电压为多少,都能做到有效适配为最终想要的结果。
下面看看测试:
public class Test2 {
public static void main(String[] args) {
DC5V dc5V = new Adapter(new AC110V());
int dc5 = dc5V.dc5V();
System.out.println("转换后的电压为:"+dc5);
}
}
输出:
转换后的电压为:5
3. 适配器的使用场景
那么,我们在哪些场景中可以使用适配器呢? 比如,app中有一个登录接口,现在有一个新的需求,需要记录登录用户的ip信息,这个在原有的接口中并没有这个参数,所以就需要添加一个ip的参数字段。 但是,如果直接在接口上改动,这样之前的app就会出现不兼容的情况,这个时候,就可以使用适配器模式来解决这个问题了,实现新老代码兼容。