适配器模式
适配器模式是作为两个不兼容的接口之间的桥梁。如插座是两脚插座不能给电脑直接使用,因为电脑的电源线基本都是三脚的,于是我们使用一个插线板连接电脑和插座,这个插线板就是一个适配器。
代码演示:
两脚插头接口:
/**
* @author objcfeng
* @description 两脚插头
* @date 2020/12/15
*/
public interface TwoPlug {
void useElectricity();
}
三脚插头接口:
//三脚插头
public interface ThreePlug {
void useElectricity();
}
插座(需要传入两脚插头的实现类才能开始供电并调用两脚插头的方法):
/**
* @author objcfeng
* @description 两脚插座
* @date 2020/11/9
*/
public class Socket {
/**
* Description: 使用插座
* @param twoPlugThings 只能支持两脚插头
*/
public void useSocket(TwoPlug twoPlugThings){
System.out.println("插座开始供电");
twoPlugThings.useElectricity();
}
}
电脑(三脚插头实现类):
/**
* @author objcfeng
* @description 电脑三脚插头
* @date 2020/11/9
*/
public class Computer implements ThreePlug {
@Override
public void useElectricity() {
System.out.println("电脑开始用电...");
}
}
可以看出,现在电脑无法使用电,因为插座的useSocket方法需要传入一个两脚插头的类型,而电脑是三脚插头的类型。我们再创建一个适配器类以适配插座和电脑。
适配器类:
/**
* @author objcfeng
* @description 适配器
* @date 2020/12/14
*/
public class Adapter implements TwoPlug {
private Computer computer;
public Adapter(Computer computer) {
this.computer = computer;
}
@Override
public void useElectricity() {
computer.useElectricity();
}
}
关键是:
适配器类实现了两脚插头,这样就能传入useSocket方法了,然后适配器类使用构造方法组合进一个Computer,并在useElectricity方法调用Computer的useElectricity方法,这样插座类调用适配器类的useElectricity方法就是调用了电脑的useElectricity方法,电脑就能用电了。
测试:
public class Main {
public static void main(String[] args) {
Computer computer = new Computer();
Socket socket = new Socket();
socket.useSocket(new Adapter(computer));
}
}
输出:
插座开始供电
电脑开始用电...
为什么使用适配器?
当现有的接口无法满足系统的需求需要引入新的接口,但是新的接口不能直接被系统直接使用时,可以使用适配器。例如,
新建一个Thread类,来执行任务,Thread构造可接收的参数有
我们一般传入一个Runnable类型的任务来执行任务,如下
Runnable task = () -> {
//执行任务
};
new Thread(task).start();
现在我们需要获取task执行完任务的返回值,或者获取到任务执行中发生的异常,该怎么做呢?
一种方法是我们可以定义一个线程安全的List来接收任务执行的结果和任务抛出的异常;但是更好的方法是,
创建一个新的接口Callable,它具有返回值并且会抛出异常。
public interface Callable<V> { /** * 计算结果,或在无法计算时引发异常。 * @return 计算结果 * @throws 异常 */ V call() throws Exception; }
创建一个适配器类用来适配Runnable和Callable
适配器接口
public interface RunnableFuture<V> extends Runnable, Future<V> { /** * Sets this Future to the result of its computation * unless it has been cancelled. */ void run(); }
而FutureTask实现了这个接口,所以我们使用这个类来适配Thread和Callable
使用:
Callable<String> task = () ->"Hello"; FutureTask<String> futureTask = new FutureTask<>(task); new Thread(futureTask).start(); String str = null; try { //获取任务的返回值 str = futureTask.get(); } catch (InterruptedException | ExecutionException e) { //处理任务执行中抛出的异常 } System.out.println(str);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。