浅谈Java设计模式系列0x06---适配器模式

前面我所介绍的都是创建型的设计模式,本篇开始我来给大家介绍结构型的设计模式;
首先我要介绍的第一个结构型的设计模式就是 适配器模式

适配器模式

适配器就是一个可以将原本并不兼容的接口能够在一起工作,而适配器模式就是为了解决这个问题;
适配器模式通过将一个不兼容的接口转换成客户所希望的接口,由此客户便可以使用相应的服务而无需修改现有的接口;
适配器模式有两种实现的方法,一种是类适配器,一种是对象适配器;

模式结构

目标抽象类(Target) :定义客户所使用的方法接口;
适配器类(Adapter) :完成从适配者到目标接口的转换适配;
适配者类(Adaptee) :定义需要适配的接口;
客户类(Client) :与符合目标接口的对象进行合作;

什么时候能用

在以下情况下可以使用适配器模式:

  • 系统需要使用现有的类,而这些类的接口不符合系统的需要;
  • 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作;

代码示例

本次我们使用手机充电的例子来给大家讲解如何通过代码实现适配器模式;
我们将使用适配器模式让安卓充电器给苹果设备充电;

  1. 类适配器
    是基于继承来实现适配器模式,适配器类(Adapter)通过继承适配者类(Adaptee)实现;
    适配器类需实现客户类所需要的接口,客户对象调用适配器类方法的时候,适配器内部调用它所继承的适配者的方法;
  2. 对象适配器
    通过组合的方式实现适配器模式,适配器类(Adapter)持有适配者类(Adaptee)的对象实例,由此来调用适配者的方法;

由于JAVA不支持多继承,而且有破坏封装之嫌,而且我们也提倡多用组合少用继承,所以下面我只提供对象适配器的代码实现;
如果对类适配器的实现感兴趣的可以自己去研究一下;
源码参考
Target接口

1
2
3
4
5
6
7
8
9
10
11
12
/**
* MicroUSB 充电接口
*/

public interface MicroUSB {
void chargeWithMicroUSB();
}
/**
* Lightning 充电接口
*/

public interface Lightning {
void chargeWithLightning();
}

Adaptee类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 具体的实现类: 安卓的充电器
*/

public class AndroidCharger implements MicroUSB {
@Override
public void chargeWithMicroUSB() {
System.out.println("charging with microUSB....");
}
}
/**
* 具体实现类: 苹果充电器
*/

public class AppleCharger implements Lightning {
@Override
public void chargeWithLightning() {
System.out.println("charging with lightning......");
}
}

Adapter类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 充电适配器,使用安卓充电器给苹果手机充电
* 实现目标类的接口(LightningInterface),然后使用组合的方式,在该适配器中定义microUsb;
* 然后在重写的 chargeWithLightning() 方法中,采用microUsb的方法来实现具体细节;
*/

public class ChargerAdapter implements Lightning {
private MicroUSB microUSB;

public ChargerAdapter() {
}

public ChargerAdapter(MicroUSB microUSB) {
this.microUSB = microUSB;
}

@Override
public void chargeWithLightning() {
microUSB.chargeWithMicroUSB();
}

public void setMicroUSB(MicroUSB microUSB) {
this.microUSB = microUSB;
}
}

Client类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 苹果手机设备
*/

public class IPhone {
private Lightning lightning;
public IPhone(){}
public IPhone(Lightning lightning) {
this.lightning = lightning;
}
public void charge(){
System.out.println("IPhone Charge start!");
lightning.chargeWithLightning();
System.out.println("IPhone Charge finish!");
}

public void setLightning(Lightning lightning) {
this.lightning = lightning;
}
}
/**
* 测试类
*/

public class Client {
public static void main(String[] args) {
ChargerAdapter adapter=new ChargerAdapter(new AndroidCharger());
IPhone iPhoe=new IPhone();
iPhoe.setLightning(adapter);
iPhoe.charge();
}
}

运行结果:

1
2
3
IPhone Charge start!
charging with microUSB....
IPhone Charge finished!

总结

适配者模式将目标类和适配者类解耦,增加了类的透明性和复用性,同时系统的灵活性和扩展性都非常好;
更换适配器或者增加新的适配器都非常方便,符合“开闭原则”;
类适配器模式的缺点是适配器类在很多编程语言中不能同时适配多个适配者类,对象适配器模式的缺点是很难置换适配者类的方法;

参考

Java设计模式之适配器模式