👉文章示例代码👈

定义

将一个类的接口转换成客户端期望的另一个接口。

适配器模式可以使原本接口不兼容的类可以一起工作。

两种模式

适配器模式有两种模式:

  • 对象适配器:采用组合方式进行类的委托
  • 类适配器:采用继承方式

三种角色

  • 目标角色(Target):客户端所期待的接口(也可以是具体类或者抽象类)。
  • 源角色(Adaptee):被适配者。已经存在的需要适配的接口或类。
  • 适配器(Adapter):将源接口转换成目标接口。只能是具体的类。

场景示例

笔者有一台吃灰蛮久的尼康相机。由于笔者的mbp只有Type-C接口,不能直接读取相机的内存卡。为此笔者还特地斥巨资买了个Type-C的扩展坞。

这里Type-C扩展坞作为内存卡和笔记本之间的适配器,只要将内存卡插入Type-C扩展坞的SD卡接口中,再将扩展坞接入到笔记本的Type-C接口中,我们就可以通过笔记本来读取内存卡中的内容。

也就是说扩展坞将笔记本的Type-C接口适配成SD卡接口。这样理解的话,SD卡接口即为我们的目标角色,Type-C接口为被适配者(即源角色),扩展坞为两者之间的适配器。

类适配器

这里先用类适配器的方式来实现下。

创建源角色

上述已经分析了,Type-C接口作为我们的源角色,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @author zhh
* @description TypeC接口类
* @date 2020-02-14 16:33
*/
public class TypeCInterface {

/**
* type-C读取
*/
public void typeCRead() {
System.out.println("Type-C接口读取...");
}
}

创建目标角色

创建目标角色,也就是SD卡接口。

1
2
3
4
5
6
7
8
9
/**
* @author zhh
* @description SD卡接口
* @date 2020-02-14 16:36
*/
public interface SDInterface {

void sdRead();
}

创建适配器

这里的适配器即Typc-C扩展坞,继承源角色,实现目标接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* @author zhh
* @description Type-C扩展坞
* @date 2020-02-14 16:43
*/
public class TypeCDockStation extends TypeCInterface implements SDInterface {

public void sdRead() {
System.out.println("SD卡接口读取...");
System.out.println("扩展坞转换");
super.typeCRead();
}
}

测试类及输出

1
2
3
4
5
6
7
8
9
10
11
12
/**
* @author zhh
* @description 测试类
* @date 2020-02-14 16:59
*/
public class Test {

public static void main(String[] args) {
SDInterface sdInterface = new TypeCDockStation();
sdInterface.sdRead();
}
}

测试类的输出结果如下:

SD卡接口读取…
扩展坞转换
Type-C接口读取…

类结构图

以上示例类的结构图如下所示
image.png

对象适配器

再来讲讲对象适配器方式的实现。

该方式中,目标角色和源角色并未发生改动,和上述类适配器方式中保持一致,这里就不做过多的代码粘贴了。

主要变化的是适配器类。

创建适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* @author zhh
* @description
* @date 2020-02-14 17:23
*/
public class TypeCDockStation implements SDInterface {

private TypeCInterface typeCInterface;

public TypeCDockStation(TypeCInterface typeCInterface) {
this.typeCInterface = typeCInterface;
}

public void sdRead() {
System.out.println("SD卡接口读取...");
System.out.println("扩展坞转换");
typeCInterface.typeCRead();
}
}

测试类及输出

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* @author zhh
* @description 测试类
* @date 2020-02-14 16:59
*/
public class Test {

public static void main(String[] args) {
TypeCInterface typeCInterface = new TypeCInterface();
SDInterface sdInterface = new TypeCDockStation(typeCInterface);
sdInterface.sdRead();
}
}

测试类的输出结果如下:

SD卡接口读取…
扩展坞转换
Type-C接口读取…

类结构图

以上示例类的结构图如下所示
image.png

总结

适用场景

  • 想使用一个已存在的类,但是该类的方法不符合接口需求。
  • 软件维护过程中,解决不同产品或者厂家功能类似而接口不同的情况。

优点

  • 提高类的透明性
  • 复用现有的类
  • 目标类和适配器类解耦,提高扩展性

缺点

  • 增加系统的复杂性
  • 增加系统代码可读难度

参考