如果去欧洲国家去旅游的话,他们的插座如下图最左边,是欧洲标准。而我们使用的插头如下图最右边
的。因此我们的笔记本电脑,手机在当地不能直接充电。所以就需要一个插座转换器,转换器第1面插
入当地的插座,第2面供我们充电,这样使得我们的插头在当地能使用。生活中这样的例子很多,手机
充电器(将220v转换为5v的电压),读卡器等,其实就是使用到了适配器模式。
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
适配器模式分为类适配器模式和对象适配器模式,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
如上图所示,插座,交流电适配器,插头的角色分别是,适配者类,适配者类,目标接口。
实现方式:定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。
案例:
现有一台电脑只能读取SD卡,而要读取TF卡中的内容的话就需要使用到适配器模式。创建一个读卡
器,将TF卡中的内容读取出来。
类图如下:
computer类
在这里插入代码片
<< interface >>SDCard 接口
/**
* @author Watching
* * @date 2023/3/19
* * Describe:scCard接口
*/
public interface SDCard {
//读
public String read();
//写
public void write();
}
SDCardImpl实现类
/**
* @author Watching
* * @date 2023/3/19
* * Describe:sdCard实现类
*/
/**
* @author Watching
* * @date 2023/3/19
* * Describe:sdCard实现类
*/
public class SDCardImpl implements SDCard {
@Override
public String read() {
String s = "读取sdCard内容";
System.out.println(s);
return s;
}
@Override
public void write() {
String s = "向sdCard编写内容";
System.out.println(s);
}
}
<< interface >>TFCard接口
/**
* @author Watching
* * @date 2023/3/19
* * Describe:tfcard接口
*
*/
public interface TFCard {
//读取卡内容
public String read();
//写卡内容
public void write();
}
TFCardImpl实现类
/**
* @author Watching
* * @date 2023/3/19
* * Describe:tfCard实现类
*/
public class TFCardImpl implements TFCard{
@Override
public String read() {
String s = "读取tfCard内容";
System.out.println(s);
return s;
}
@Override
public void write() {
String s = "向tfCard编写内容";
System.out.println(s);
}
}
AdapterTF适配器类
需要继承TFCardImpl实现类,同时还要实现SDCard接口。
重写SDCard接口中的方法,但实际上方法中调用的是父类TFCardImpl的方法
/**
* @author Watching
* * @date 2023/3/19
* * Describe:适配器类 令电脑读取sdCard的功能也能读取tfCard
*/
public class AdapterTF extends TFCardImpl implements SDCard{
@Override
public String read() {
return super.read();
}
@Override
public void write() {
super.write();
}
}
Computer类
/**
* @author Watching
* * @date 2023/3/19
* * Describe:电脑类
*/
public class Computer{
//电脑类有一个读取sd卡的功能
public void read(SDCard sdCard){
if(sdCard == null){
throw new NullPointerException("sdcard can not be null");
}
sdCard.read();
}
}
client测试类
/**
* @author Watching
* * @date 2023/3/19
* * Describe:测试类
*/
public class Client {
public static void main(String[] args) {
Computer computer = new Computer();
//Computer的read()方法需要传递一个SDCard接口的实现类,而AdapterTF也是SDCard的实现类,
// 且AdapterTF同时继承了TFCard的实现类,并在read和write方法中实际调用返回的是TFCard的方法
computer.read(new AdapterTF());
System.out.println("=================");
computer.read(new SDCardImpl());
}
}
Computer的read()方法需要传递一个SDCard接口的实现类,而AdapterTF也是SDCard的实现类,
且AdapterTF同时继承了TFCard的实现类,并在read和write方法中实际调用返回的是TFCard的方法
程序运行结果
但是类适配器模式违背了合成复用原则。应该优先使用组合或者聚合,而不是继承
实现方式:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中(不再是Adapter类继承TFCardImpl实现类,而是将其对象聚合进Adapter类),该类同时实现当前系统的业务接口。
将上面的案例进行改写,类图如下:
上面案例中的代码我们只需要修改适配器AdapterTF类和测试类Client
AdapteTF类
/**
* @author Watching
* * @date 2023/3/19
* * Describe:适配器类 令电脑读取sdCard的功能也能读取tfCard
*
* 对象适配器的适配器类和类适配器的适配器类的区别:
* 对象适配器的适配器类不需要继承目标接口
*/
public class AdapterTF implements SDCard {
//聚合适目标接口的实现类
private TFCard tfCard;
public AdapterTF(TFCard tfCard){
this.tfCard = tfCard;
}
@Override
public String read() {
return tfCard.read();
}
@Override
public void write() {
tfCard.write();
}
}
测试类Client
/**
* @author Watching
* * @date 2023/3/19
* * Describe:测试类
*/
public class Client {
public static void main(String[] args) {
Computer computer = new Computer();
//Computer的read()方法需要传递一个SDCard接口的实现类,而AdapterTF也是SDCard的实现类,
// 且AdapterTF同时继承了TFCard的实现类,并在read和write方法中实际调用返回的是TFCard的方法
computer.read(new AdapterTF(new TFCardImpl()));
System.out.println("===========================");
computer.read(new SDCardImpl());
}
}
当电脑只有读取SD卡功能,而又需要读取TF卡功能时可以这样编写。且如果还需要增加一个读取A卡功能,我们只需要添加一个读取A卡功能的接口,和一个其实现类。再将这个接口聚合进Adapter,就可以实现了,不需要更改电脑原本的代码。
当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter ,实现所有方法。而此时我们只需要继承该抽象类即可。