【接口回调】关于接口回调的理解

什么是回调?

在一个系统中,模块之间难免会存在一些调用关系,调用关系从调用方式上来看可以分为两种:

  • 同步调用
  • 异步调用

同步调用:同步调用是一种阻塞式的,就比如A对象中的一个方法调用了B对象的方法,那么A方法必须等B的方法执行完才能继续执行。

异步调用:异步调用是一种非阻塞式的调用方式,解决了同步调用的阻塞问题,例如A再调用B之后和B一起继续执行。类似于主线程中,创建了一个子线程,二者并行。

回调:而在同步调用和异步调用中又分为同步回调异步回调,其目的都是为了降低,模块之间的耦合度。也可以理解为A调用了B,但B是一个抽象的方法没有被实现,在系统调用A时则需要实现B方法(可以通过匿名内部类来重写方法或者也可以传入一个实现类),这样的写法大大降低了耦合度。

Java中的接口回调

例:我们来实现一个下载工具,首先需要一个下载的执行器:Download ,下载成功后的资源解析或封装等操作,所以需要一个后续的操作的处理器 Processor,此外还需要一个下载日志打印下载成功或失败的信息 Log。

下载执行器Download:

public class DownLoad {
    private Log log;
    private Processor processor;

    public DownLoad(Log log, Processor processor) {
        this.log = log;
        this.processor = processor;
    }
    /**
     * 异步下载
     */
    public void download(URL url) {

        new Thread(()->{
            //下载前的日志打印
            log.beforeLog();
            //下载资源(为了降低耦合度 瞎子资源的方法也可以封装)
            try {
                //建立HTTP连接
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                //获取连接的输入流
                InputStream in = urlConnection.getInputStream();
                int len = 0;
                byte[] bytes = new byte[1024];
                FileOutputStream out = new FileOutputStream("回答.m4a");
                while((len = in.read(bytes)) != -1){
                    out.write(bytes,0,len);
                }
                out.close();
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //下载成功后,后续的处理(如果不用回调直接写业务逻辑,耦合度高)
            processor.parse();
            processor.pack();
            //资源处理后的日志打印
            log.afterLog();
        },"download").start();
    }
}

日志接口规范 Log:

public interface Log {
    default void beforeLog(){};
    default void afterLog(){};
}

后续处理器 Processor:

public interface Processor {
    default void parse(){};
    default void pack(){};
}

现在利用我们已经写好的下载器来实现一个下载音乐的demo.

Demo:

日志实现类 LogImpl

public class LogImpl implements Log {
    @Override
    public void beforeLog() {
        System.out.println("开始下载");
    }

    @Override
    public void afterLog() {
        System.out.println("下载完成");
    }
}

后续资源处理器实现类 ProcessorImpl

public class ProcessorImpl implements Processor {
    @Override
    public void pack() {
        System.out.println("资源解析");
    }
}

主函数:

public class Main {
    public static void main(String[] args) throws MalformedURLException {
        DownLoad downLoad = new DownLoad(new LogImpl(), new ProcessorImpl());
        downLoad.download(new URL("https://m801.music.126.net/20221126204509/2cf0dcbbf85aafe0a3865e11c1ab3edf/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/22329640882/80f4/43a8/71f2/4816f6be3429bab46bd192968a9c0de0.m4a"));
    }
}

Demo执行结果:
在这里插入图片描述

【接口回调】关于接口回调的理解_第1张图片

总结:

上述实现下载器过程中,接口回调发生在 日志 和 后续处理程序时,这里我们定义了一个Log接口,然后执行器中调用该接口的beforeLog和afterLog方法,执行时LogImpl重写了这两个方法。实现了接口回调,这更方便我们自定义日志信息。修改信息时只需要修改重写的方法而不需要更改执行器中的方法,降低了程序的耦合度。

你可能感兴趣的:(Java基础,java,前端,算法)