适配器模式

定义

将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口兼容而不能一起工作的那些类能一起工作。
适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

适用场景

  • 已经存在的类,它的方法和需求不匹配时(方法结果相似或相同);
  • 不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案。

优点和缺点

优点

  • 客户端通过适配器可以透明地调用目标接口;
  • 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类;
  • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题;
  • 符合开闭原则。

缺点

  • 适配器编写过程需要全面考虑,可能会增加系统的复杂性;
  • 增加系统代码可读的难度。

结构

  • 目标接口: 当前系统业务所期待的接口,它可以是抽象类或者接口;
  • 适配者类: 它是被访问和适配的现存组件库中的组件接口;
  • 适配器类: 它是一个转换器,通过继承或者引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

类结构型模式

代码实现

我们生活中经常会给手机充电,但是标准电压是交流电220V,但是我们的手机一般是使用直流电5V的,我们可以用代码来演示一下这个过程的实现。

首先我们创建一个适配者类,也就是我们220V交流电

1
2
3
4
5
6
7
8
public class AC220 {

public int outputAC220V() {
int output = 220;
System.out.println("输出交流电" + output + "V");
return output;
}
}

然后我们创建目标接口,也就是我们需要的5V直流电

1
2
3
public interface DC5 {
int outputDC5V();
}

创建适配器类,也就是实现我们交流200V转换直流5V的类,可以理解为手机充电器

1
2
3
4
5
6
7
8
9
10
public class PowerAdapter extends AC220 implements DC5 {
@Override
public int outputDC5V() {
int adapterInput = super.outputAC220V();
//业务处理
int adapterOutput = adapterInput / 44;
System.out.println("使用PowerAdapter输入AC: " + adapterInput + "V;输出DC: " + adapterOutput + "V");
return adapterOutput;
}
}

测试类调用

1
2
3
4
5
6
public class Test {
public static void main(String[] args) {
DC5 dc5 = new PowerAdapter();
dc5.outputDC5V();
}
}

输出结果

1
2
输出交流电220V
使用PowerAdapter输入AC: 220V; 输出DC: 5V

UML类图

对象结构型模式

代码实现

同样以上述实例做演示,代码实现只有适配器类中有所不同

首先我们创建一个适配者类,也就是我们220V交流电

1
2
3
4
5
6
7
8
public class AC220 {

public int outputAC220V() {
int output = 220;
System.out.println("输出交流电" + output + "V");
return output;
}
}

然后我们创建目标接口,也就是我们需要的5V直流电

1
2
3
public interface DC5 {
int outputDC5V();
}

创建适配器类,也就是实现我们交流200V转换直流5V的类,可以理解为手机充电器
类结构型模式是通过继承AC220类来调用方法的,对象结构模式则是通过组合来做的

1
2
3
4
5
6
7
8
9
10
11
public class PowerAdapter implements DC5 {
private AC220 ac220 = new AC220();
@Override
public int outputDC5V() {
int adapterInput = ac220.outputAC220V();
//业务处理
int adapterOutput = adapterInput / 44;
System.out.println("使用PowerAdapter输入AC: " + adapterInput + "V;输出DC: " + adapterOutput + "V");
return adapterOutput;
}
}

测试类调用

1
2
3
4
5
6
public class Test {
public static void main(String[] args) {
DC5 dc5 = new PowerAdapter();
dc5.outputDC5V();
}
}

输出结果

1
2
输出交流电220V
使用PowerAdapter输入AC: 220V; 输出DC: 5V

UML类图

接口适配器

代码实现

接口适配器和上面两种略有不同
假设我们现在有一个接口,里面有多个方法,但是我们只想使用其中的一个方法,那么就可以使用一个抽象类,来继承这个接口,并实现这个接口的所有方法,不做任何业务逻辑处理,
我们具体想要实现逻辑的类,就可以继承这个抽象类,然后去重写自己想要使用的方法即可。

首先有一个接口,里面有多个方法

1
2
3
4
5
6
7
public interface Interface1{
void m1();
void m2();
void m3();
void m4();
void m5();
}

我们只想用其中的m1方法,如果直接实现接口的话,需要实现所有的方法
我们就可以先创建一个抽象类,去实现这个接口,然后空实现所有的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public abstract class AbstractAdapter implements Interface1{
@Override
public void m1() {
}
@Override
public void m2() {
}
@Override
public void m3() {
}
@Override
public void m4() {
}
@Override
public void m5() {
}
}

然后我们具体的业务类就可以继承这个抽象类,实现自己需要的方法就可以了

1
2
3
4
5
6
7
8
public class Test extends AbstractAdapter {

@Override
public void m1() {
//业务逻辑
}
}

UML图