一、什么是适配器
如果你的电器是一个两项的插头,而电源插座是三项的,那就需要一个交流电适配器。这个适配器位于两项插头和三项插座的中间,他的工作是将三项插座转成两项插座,好让两项插头可以插进这个插座得到电力,也可以说,适配器改变了插座的接口,以符合两项插头的需求。
image.png
二、面向对象适配器
假设已有一个软件系统,希望他能和一个新的厂商类库搭配使用,但是这个新厂商所设计出来的接口,不同于旧厂商的接口:
image.png
不改变现有代码,怎么解决这个问题呢?可以写一个类,将新厂商接口转接成所期望的接口。
image.png
A、具体的面向对象适配器的例子
设计一个TypeC与USB的转接
1、TypeC接口
public interface TypeC {
void isTypeC();
}
2、USB接口
public interface USB
void isUsb();
}
3、实现USB接口
public class Usb implements USB {
@Override
public void isUsb() {
System.out.println("USB口");
}
}
4、适配器
//implement是想转换的类型接口,也就是客户希望看到的接口
public class UsbAdapter implements TypeC {
USB usb;
//取得要适配的对象的引用,这里利用构造器取得
public UsbAdapter(USB usb) {
This.usb = usb;
}
@Override
public void isTypeC() {//实现TypeC接口中的方法,实际上调用的是usb的方法
usb.isUsb();
}
}
5、测试一下
public class TypeCDrive {
public static void main(String[] args) {
//创建一个USB
USB usb = new USB();
//将USB包装进USB适配器中,使他看起来像个TypeC
TypeC usbAdapter = new UsbAdapter(usb)
//传入一个假装是TypeC的USB
testTypeC(usbAdapter);
}
//取得TypeC并调用isTypeC方法
static void testTypeC(TypeC typeC) {
typeC.isTypeC();
}
}
6、结果
USB口
可以看出当testTypeC被调用时,不知道实际传入的是一个假装TypeC的USB
B、适配器模式
将一个类的接口,转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以合作无间。
面向对象适配器类图
image.png
适配器模式使用对象组合,以修改的接口包装被适配者,被适配者的任何子类都可以搭配着适配器使用。
三、类适配器
类适配器需要多重继承才能实现,Java中是无法实现的,但是在使用多重继承语言时,可以使用它。
A、类图
image.png
对象适配器使用组合的方式将请求传送给被适配者
类适配器采用的是继承的方式实现。
四、真实的应用
Java在早期的集合(collection)类型(如:Vector,Stack,Hashtable)都实现了一个名为elements()的方法,该方法会返回一个Enumeration。这个Enumeration接口可以循环遍历集合内的每个元素,而无需知道他们在集合内如何被管理的。
image.png
当Sum更新集合类后,开始使用Iterator接口了,这个结婚和枚举接口很像,都可以遍历集合内元素,但是Iterator还提供了删除的功能。
image.png
对于遗留代码,暴露出枚举的接口,但是在新代码中,只使用迭代器,要解决这个问题,就需要构造一个适配器。
那么就先看看这两个接口,都有什么关系吧,也就是说,要找出每一个适配器在被适配者中的对应方法是什么。
image.png
类图
image.png
因为枚举不支持删除,所以适配器无法实现一个有实际功能的remove()方法,所以讲remove()方法定义成会抛出UnsupportedOpeartionException。
实现:
//适配器需要实现迭代器的接口,让他看起来就是一个迭代器implements Iterator
public class EnumerationIterator implements Iterator {
Enumeration enum;
//利用组合的方式,将枚举结合进适配器中,用一个实例变量记录枚举
public EnumerationIterator (Enumeration enum) {
This.enum = enum;
}
//迭代器的hasNext()方法实际委托给枚举的hasMoreElements()方法
public boolean hasNext() {
return enum.hasMoreElements();
}
//迭代器的next()方法实际委托给枚举的nextElements()方法
public Object next() {
return enum.nextElement();
}
//无法支持迭代器的remove()的方法,只能抛出异常
public void remove() {
throw new UnsupportedOpeartionException();
}
}