资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

设计模式之适配器模式

Java 更新时间: 发布时间: 计算机考试归档 最新发布

设计模式之适配器模式

文章目录

    • 1、适配器模式基本介绍
    • 2、场景推导
    • 3、Jdk中的适配器模式

1、适配器模式基本介绍

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁,将一个类的接口转换成客户希望的另一个接口, 使得原本由于接口不兼容不能在一起工作的类,可以在一起工作

2、场景推导

需求:计算两数之和

我们这样实现

class Calc {	public int add(int a, int b) {		return a + b;	}}public class AdapterApp {	public static void main(String[] args) {				Calc ca = new Calc();				int r = ca.add(1, 2);				System.out.println(r);//3				}}

现在变化来了,客户想要计算三个数的和,怎么办呢

好,有小伙伴说,那还不简单,我传入参数的时候再调一次add方法不就行了

class Calc {    public int add(int a, int b) {        return a + b;    }}public class AdapterApp {    public static void main(String[] args) {        Calc ca = new Calc();        int r = ca.add(1, ca.add(2,3));        System.out.println(r);//6    }}

那你要这样玩的话,就没得聊了

言归正传,我们考虑用适配器模式解决

class Calc {    public int add(int a, int b) {        return a + b;    }}//适配器class CalcAdapter {    // 注意组合优于继承    private final Calc calc;    public CalcAdapter(Calc calc) {        this.calc = calc;    }    public int add(int x, int y, int z) {        return calc.add(calc.add(x,y), z);    }}------------------------------------------------------------------------------public class AdapterApp {    public static void main(String[] args) {        CalcAdapter ca = new CalcAdapter(new Calc());        int r = ca.add(1, 2, 3);        System.out.println(r);//6    }}

我们看一下适配器模式做了什么事,以前add()方法只能传两个参数

但是用户的需求变了,用户想传三个参数,适配器做到了适配,后面4个参数,5个参数…都可以扩展

好了,是不是感觉适配器模式很简单呢

接下来看看在生产中设计模式的运用

3、Jdk中的适配器模式

在java线程里面的Runnable和Callable两个接口是通过适配转换的

写一段代码:

public class ThreadTest {    // 线程池,线程任务提交给线程池执行    public static ExecutorService executorService = Executors.newFixedThreadPool(10);    public static void main(String[] args) throws ExecutionException, InterruptedException {        // 线程池运行Runnable方式        FutureTask> futureTask01 = new FutureTask<>(new Runnable() {            @Override            @SneakyThrows            public void run() {                System.out.println("线程池运行Runnable方式");                Thread.sleep(3000);            }        }, String.class);        executorService.submit(futureTask01);        // 线程池运行Callable方式        FutureTask futureTask02 = new FutureTask<>(new Callable() {            @Override            public String call() throws Exception {                Thread.sleep(3000);                System.out.println("线程池运行Callable方式");                // 返回一句话                return "线程池运行Callable方式返回:" + Thread.currentThread().getName();            }        });        executorService.submit(futureTask02);        System.out.println(futureTask02.get());    }}

可以看到创建了两种不同类型的任务:

  • 一种是基于Runnable接口,是无返回值的任务;
  • 一种基于Callable接口,是有返回值类型的任务

但是,居然都可以通过executorService#submit()方法提交到线程池中运行?难道这个方法是一个重载方法吗?

其实我们点进源码里面进行参看,发现是同一个方法

看来是FutureTask这个类搞得鬼,接下来我们看FutureTask类的两个构造器

// 使用 Callable 进行初始化public FutureTask(Callable callable) {    if (callable == null)        throw new NullPointerException();    this.callable = callable;    this.state = NEW;       // ensure visibility of callable}// 使用 Runnable 初始化,并传入 result 作为返回结果。// Runnable 是没有返回值的,所以 result 一般没有用,置为 null 就好了public FutureTask(Runnable runnable, V result) {    this.callable = Executors.callable(runnable, result);    this.state = NEW;       // ensure visibility of callable}

看这一行代码Executors.callable(runnable, result),明明写的是Executors#callable,但是传进去的确是一个Runnable,我们进去看看

public static  Callable callable(Runnable task, T result) {    if (task == null)        throw new NullPointerException();    // 在这里进行了适配,将Runnable -> Callable    return new RunnableAdapter(task, result);}
//RunnableAdapter类static final class RunnableAdapter implements Callable {    final Runnable task;    final T result;    RunnableAdapter(Runnable task, T result) {        this.task = task;        this.result = result;    }    public T call() {        task.run();        return result;    }}

发现没有这个类,长得像什么,像适配器,首先它实现了Callable接口,又组合了Runnable接口,并且通过写了一个和Callable同名的call方法将Runnable#run

  • 这是非常典型的适配模型,想要把 Runnable 适配成 Callable,首先要实现 Callable 的接口,接着在 Callable 的 call 方法里面调用被适配对象(Runnable)的方法
  • 当然也可以将Callable适配成Runnable类,那为什么不呢?因为Callable可以提供更多的方法,例如获取返回值

可能有同学觉得,好像还是很简单,我只要记住适配器类继承要适配对象的抽象类,并组合适配对象就行了,这也不难嘛

确实关键点就是这两步,但是这种解耦、开闭的思想我们一定要融入平时的编码中

转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/1096214.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【设计模式之适配器模式】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2