设计模式之适配器模式
1. 概要
如果你希望使用一个接口,来访问一个非该接口的实现类,也就是不兼容的类,可以使用适配器模式
适配器模式是结构型模式,可以使用不兼容的对象相互合作 ,即,将一个接口转换成另一个接口
2. 结构
- 目标:当前业务用的接口
- 适配者:实际的接口,类
- 适配器:通过适配器访问适配者
3. 使用场景
- 当你希望使用某个类, 但是其接口与其他代码不兼容时, 可以使用适配器类。
4. 优缺点
- 优点
- 单一职责
- 开闭
- 缺点
- 代码复杂度增加,要增加多个类
5. 举个栗子
- 一台电脑,使用的是usb接口,现在需要操作一张SD卡,老式手机上的那种,现实生活中有“读卡器”,读卡器即适配器
- 电脑,注意这里的方法接收的是一个
UsbDisk
接口(下面定义),所以方法实参必需是它的实现类
public class Computer {
public String readData(UsbDisk usbDisk) {
return usbDisk.readUsb();
}
}
- usb接口
public interface UsbDisk {
// 读取数据
String readUsb();
// 写入数据
void writeUsb(String data);
}
- usb实例(比如:U盘)
public class UsbDiskImpl implements UsbDisk {
@Override
public String readUsb() {
return "read usb form usb disk ";
}
@Override
public void writeUsb(String data) {
System.out.println("write data : " + data);
}
}
- sd卡接口(记不记得,读卡器上面有个SD卡的接口)
public interface SdCard {
// 读取SD卡数据
String readSd();
// 写入sd卡
void writeSd(String data);
}
- sd卡实例
public class SdCardImpl implements SdCard {
@Override
public String readSd() {
return "read data form sdcard";
}
@Override
public void writeSd(String data) {
System.out.println("write data : " + data);
}
}
- 适配器(读卡器)
- 实现的应该是USB,因为要插入电脑的USB接口。继承sd卡实例,身上插的是实际sd卡
- 依照合成复用原则,依赖 > 继承,所以使用依赖注入的方式
public class SdCardAdapter implements UsbDisk {
// 使用依赖,SD卡实例(多态)
private SdCard sdCard;
public void setSdCard(SdCard sdCard) {
this.sdCard = sdCard;
}
@Override
public String readUsb() {
// 调用适配者的方法
return sdCard.readSd();
}
@Override
public void writeUsb(String data) {
// 调用适配者的方法
sdCard.writeSd(data);
}
}
- 调用
- readData方法想要接收的是一个usb接口,现在使用适配器间接的调用了sdcard
public class Client {
public static void main(String[] args) {
// 创建一个适配器
SdCardAdapter sdCardAdapter = new SdCardAdapter();
// 适配哪个实例
sdCardAdapter.setSdCard(new SdCardImpl());
// 使用适配,readData方法想要接收的是一个
String data1 = computer.readData(sdCardAdapter);
System.out.println(data1);
}
}
6. JDK源码探究
- 在有时想要把一组数据转换成list集合,常常使用
Arrays.asList()
, - 但这个方法转换出的结果,严格来说,并不是一个真正意义上的List集合,而是一个适配器,它目的是,让我们以操作一个集合的形式,去操作一个数组
- 所以它转换出的对象底层还是一个不可变的数组,不可添加数据
- 转换出的对象实际上是一个
Arrays
的内部类,继承了AbstractList
,间接实现了List
- 对应的角色:目标:
List
,适配者:数组private final E[] a
,适配器:Arrays$ArrayList<E>
- 添加一个数据试试看