适配器模式真的很简单
提到设计模式,就有一种高逼格的感觉。其实不然,比如这篇文章要说的适配器模式,真的就很简单。简单到很多面向对象语言的初学者在不知不觉中就用到了,只是自己不知道而已。生活中有很多适配器的例子,如电压转换器、各种接口转换器等等。下面就以电脑外设接口为例说明。
本屌丝的电脑接口为USB,假设要接入我这台电脑使用的外设都需要实现 USB 接口才行,抽象为程序如下:
首先定义一个USB接口,接口中有一个抽象方法,表示拥有USB接口。
1
2
3
public interface USB {
void hasUSB();
}
然后定义两个类,表示有USB接口的键盘和鼠标:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class UsbKeyboard implements USB {
@Override
public void hasUSB() {
System.out.println("USB键盘有usb接口,能接上电脑使用");
}
}
public class UsbMouse implements USB {
@Override
public void hasUSB() {
System.out.println("USB鼠标有usb接口,能接上电脑使用");
}
}
测试类如下:
1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
public static void main(String[] args) {
USB usbDevice1 = new UsbKeyboard();
USB usbDevice2 = new UsbMouse();
canBeUsedForComputer(usbDevice1);
canBeUsedForComputer(usbDevice2);
}
public static void canBeUsedForComputer(USB usbDevice){
usbDevice.hasUSB();
}
}
该类很简单。有一个静态方法,canBeUsedForComputer,他接收一个实现USB接口类型的参数。结果如下:
USB键盘有usb接口,能接上电脑使用 USB鼠标有usb接口,能接上电脑使用
可是最近我下了个2K17的游戏,想体验好点,买了个游戏手柄,是 PS/2接口的。代码如下:
1
2
3
4
5
6
7
8
9
public interface PS2 {
void hasPS2();
}
public class PS2Handler implements PS2 {
public void hasPS2(){
System.out.println("PS2游戏手柄有PS2接口,使用转换器之后能连接电脑使用");
}
}
同样的先顶一个PS2接口,让游戏手柄类实现这个接口,可是现在调用 Test 类中的 canBeUsedForComputer 方法不行了,因为我的电脑只支持USB接口。怎么办,显然我需要一个转换器。这个转换器可以看作是对PS/2接头的一个包装,这个包装抽象出的类应该有如下特点:
- 这样的转换器包装的是PS/2接头的外设,所以它应该持有一个PS/2接头的对象。
- 经过包装之后能接在电脑上使用的,所以它应该实现USB接口。
- 跟电脑实现交互的是转换器,而实际提供功能的还是PS/2接头的外设。
清楚了这些,代码就容易实现了,定义一个 PS2 的包装类:
1
2
3
4
5
6
7
8
9
10
11
12
public class PS2Wrapper implements USB{
private PS2 mPS2;
public PS2Wrapper(PS2 mPS2) {
this.mPS2 = mPS2;
}
@Override
public void hasUSB() {
mPS2.hasPS2();
}
}
这样,PS2Wrapper 就实现了将实现 PS2 接口的类的实例对象转换成了实现 USB 接口的类的实例对象。然后就可以在Test 类中调用 canBeUsedForComputer 方法了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
public static void main(String[] args) {
USB usbDevice1 = new UsbKeyboard();
USB usbDevice2 = new UsbMouse();
USB usbDevice3 = new PS2Wrapper(new PS2Handler());
canBeUsedForComputer(usbDevice1);
canBeUsedForComputer(usbDevice2);
canBeUsedForComputer(usbDevice3);
}
public static void canBeUsedForComputer(USB usbDevice){
usbDevice.hasUSB();
}
}
输出结果如下:
USB键盘有usb接口,能接上电脑使用 USB鼠标有usb接口,能接上电脑使用 PS2游戏手柄有PS2接口,使用转换器之后能连接电脑使用
上面就是Adapter模式的实现,百度百科定义是:将一个类的接口适配成用户所期待的,一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。
最后总结一下:Adpater能够让各个类之间相互协作,而不受不兼容接口的影响。我这里使用的都是接口的形式,实际使用中也可针对抽象类进行包装,视具体场景而定,其本质就是面向对象的三大特性。