设计模式学习笔记(2)适配器

本文实例代码:https://github.com/JamesZBL/java_design_patterns

适配器(Adapter)模式用来将两个不同的接口进行适配,所以它是一种结构型的模式。适配器可以实现把一种接口进行转换,从而能够适应客户端的需求,所以它解决了两个类之间因为接口不匹配而无法工作的问题。适配器在日常生活中也很常见,比如 Micro-SD 卡需要一个转换器才在大多数的笔记本上存取数据,两脚插头需要转换器才能在只提供三脚插孔的插座上使用,Micro-USB 的数据线需要转换器才能在只具备 Type-C 的接口的设备之间传输数据等等…… 这些转换设备都属于适配器,它们都将一种接口转换成另一种接口,而使用者只需了解转换设备如何使用即可,无需关注其内部实现逻辑。

实例

老张有辆小汽车,他每天都开着它上下班,我们将小汽车抽象成 Car 接口:

Car.java

1
2
3
4
public interface Car {

void drive();
}

老张驾驶小汽车很熟练,所以老张(司机)实现了 Car 接口

Driver.java

1
2
3
4
5
6
7
8
9
10
public class Driver implements Car {
private Car car;
@Override
public void drive() {
car.drive();
}
public Driver(Car car) {
this.car = car;
}
}

某个周末,他的小汽车被朋友借走了,但是公司突发紧急情况需要他马上赶到公司。打了一圈电话之后发现,只有一个开大巴的朋友的车当天没有任务,思考了片刻后,老张还是把大巴车借过来了(有点扯了,不过当初代码写成这样的时候并不觉得扯,所以继续扯下去吧)。他之所以能把大巴车借来,是因为他自己是有大车的驾驶证的,他又犹豫了片刻是因为他已经多年没有驾驶过大车了。

驾驶小汽车的方式和大巴车是有一定差别的,这只大巴车的接口 Bus:

Bus.java

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

private static final Logger LOGGER = LoggerFactory.getLogger(Bus.class);

public void run() {
LOGGER.info("公共汽车在行驶");
}
}

老张上车后发现对车上的各种设备都不熟悉,于是向车主朋友请教,经过朋友几分钟的讲解,老张经过和小汽车的类比,将自己驾驶大车的技能又“激活”了,这时的老张就可以被视为一种适配器,我们将他抽象为 BusAdapter

BusAdapter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
public class BusAdapter implements Car {

private Bus bus;

public BusAdapter() {
this.bus = new Bus();
}

@Override
public void drive() {
bus.run();
}
}

有了这个“适配器”,大巴车成功的被开到了公司:

1
2
3
4
5
6
7
public class Application {

public static void main(String[] args) {
Driver driver = new Driver(new BusAdapter());
driver.drive();
}
}

总结

适配器模式的使用场景有:

  • 需要使用的类的接口与需要的接口类型不匹配
  • 需要创建一个可重用的类,它可以与不相关的或不可预见的类进行协作,也就是说,类不一定具有兼容的接口
  • 需要使用几个现有的子类,但是通过子类化每个子类来调整它们的接口是不切实际的。对象适配器可以调整其父类的接口

适配器又可以分为对象适配器和类适配器,上面的实例就是类适配器的一种,类适配器和对象适配器的却别有:

  • 类适配器的适配功能是通过被适配类(接口)的一个对象间接完成的。因此,类适配器不能无法
    对被适配类的所有子类进行适配
  • 类适配器重写了被适配类(接口)的方法,所以,类适配器可以看做被适配类(接口)的一个子类,上面例子中的 BusAdapter 类就可以视为 Car 的一个子类
  • 类适配器一般只需持有一个被适配类(接口)的对象,并不需要额外的对被适配类(接口)的引用, BusAdapter 只对 Car 接口进行了适配
  • 对象适配器可以和多个被适配类(接口)的对象协同工作——即被适配类(接口)本身及其所有子类。适配器也可以一次为所有的被适配类(接口)添加自定义的功能
  • 对象适配器使得重写被适配类(接口)的方法变成了不可能,这时需要的是被适配类(接口)的子类,而不是被适配类(接口)本身

适配器模式的主要目的是解决接口之间不匹配的问题,所以它经常被用来解决现有设计中结构设计问题,使得软件在不修改既有类或接口的情况下实现新的功能组合。

分享到: