浅谈“回调”在程序设计中的好处

1:回调还是返回(return)

在写代码的时候,我们经常碰到这样的场景:调用一个函数或者方法时需要返回多个值给上级调用者,如示例:

void methodA(){
   Wrap w = methodB(); 
   w.one; //use
   w.two;
}

Wrap methodB(){
    do something;
    return Wrap;
}

class Wrap{
   Type one;
   Type two;
}

上面是我刚开始写代码时候常用的方式,在多个类型的基础上再封装一个类,返回这个类类型给上层程序处理。在类似情景不多的情况下,采用这种处理方式 是可以接受的。慢慢的,当一个Project的代码越来越多,类似的情况出现频繁的时候,我就开始感到这种处理方式恶心的地方了。

1:为了返回几个不同类型的值,多出来了一个奇怪的类(还得为它想个名字,赋值(set),取值(get),多了n行代码)....

2:返回结果为null ? 为什么会出现null, 出现后怎么处理? 通过向上层抛出异常来处理?每一次遇到这种情况还得回去看原先写的代码,各种陷阱啊~~

更优雅的方式:

interface Callback{
    void onCall(Integer one,String two);
    void onFail(errorMsg);
}

void methodA(){
   methodB(new Callback(){
        void onCall(Integer one,String two){
              //取得返回值  
        }
        void onFail(errorMsg){
             //失败
       }
   }); 
}

void methodB(Callback call){
    if(success){ //正常
        call.onCall(one,two);//one和two为变量
    }else{ //有状况
        call.onFail(‘get fail‘);
    }
}

现在处理返回结果就好多了,代码的可读性也得到了增强,当然,如果你要求返回的结果非常多,还是要封装成一个类比较好点~

2:事件通知

我们先来看一段常用的JS代码

$(‘#id‘).click(function(){
   alert(‘click‘);
});

这段代码的工作流程大概就是浏览器捕获到输入设备(鼠标)的点击状态,然后执行click里面的匿名函数,完成整个回调的过程。

类似的情形我们还可以看到很多,尤其在UI的编程中,很多库几乎就是基于事件模型来编写的。下面我们来模拟下载文件进度的事件监听。

interface OnLoadListener{
   /**
    *@param progress 进度(百分比)
    */
   void onLoad(double progress);
}

void download(url,OnLoadListener listener){
    InputStream is = getStreamOfUrl(url); //
    double totalLen = is.ContentLength; //文件长度 
    int readLen = 0, hReadLen;
    while((readLen=is.read())!=-1){ //从网络上读取.
         hReadLen += readLen;
         listener.onLoad(hReadLen/totalLen); //把结果即时返回.
    }
}

//当我们在UI层调用时:
void show(){
  download("http://www.darcye.com/file",new OnLoadListener(){
       void onLoad(double progress){
             //显示进度
       }
  });
}

当然,这里只是简单的示例,目的在于说明回调在事件编程模型中的作用。实际上,还有异步,事件队列等许多问题需要进行考虑。

3:分离变化和不变的部分

我们知道,算法的步骤是一样的,只是数据源的类型不一致而已。因此我们可以想办法把不变的算法给分离出来。

相信了解Java的朋友都知道,在API中对对象的排序就是通过回调来解决这个问题的。也就是一种著名的设计模式-模板方法。让我们来看看它的实现过程吧。

我们从这个方法出发:

void java.util.Arrays.sort(T[] a, Comparator
   
    c)

深入源码很容易知道,排序的算法就是在这里实现的了,可以看到实现的是合并排序(merge sort)。排序根据(变化的部分)的关键就是这个接口Comparator,再深入代码就可以看到其会回调响应对象实现的接口方法compareTo()。

原文地址: 浅谈“回调”在程序设计中的好处

浅谈“回调”在程序设计中的好处

时间: 2024-11-06 03:36:48

浅谈“回调”在程序设计中的好处的相关文章

浅谈回调函数

最近学习js的异步执行,用到回调函数,对这个机制不是很理解,故查了一些资料,在此整理分享一下自己的理解. 维基百科对回调函数的定义: 在计算机程序设计中,回调函数,或简称回调(Callback 即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代码的,某一块可执行代码的引用.这一设计允许了底层代码调用在高层定义的子程序. 知乎上一个网友提供的生动描述: 你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打

浅谈javascript和java中的数组

javascript中的数组 数组的创建 直接创建方式  var str = ['java', 'js']; 使用new创建方式: var a = new Array(10);  //  定义长度为10的数组(可变) 另类new创建方式:var a = new Array(1, 2, 3, 4, 5);  var b = [1, 2, 3, 4, 5]; 二维数组(多维)创建方式:var a = new Array([1,2,3], [4,5,6], [7,8,9]);  var b = [[1

浅谈Chrome V8引擎中的垃圾回收机制

垃圾回收器 JavaScript的垃圾回收器 JavaScript使用垃圾回收机制来自动管理内存.垃圾回收是一把双刃剑,其好处是可以大幅简化程序的内存管理代码,降低程序员的负担,减少因 长时间运转而带来的内存泄露问题.但使用了垃圾回收即意味着程序员将无法掌控内存.ECMAScript没有暴露任何垃圾回收器的接口.我们无法强迫其进 行垃圾回收,更无法干预内存管理 内存管理问题 在浏览器中,Chrome V8引擎实例的生命周期不会很长(谁没事一个页面开着几天几个月不关),而且运行在用户的机器上.如果

浅谈Observer在代码中表现形式

说到观察者模式,基本在软件工程领域中是应用广泛,不知道的可以先学习一番,下面给个快速的回顾,然后在通过一个grpc中的responseObserver谈下观察者对象在代码中的位置. 喜欢类图,就不上其他图了,只有能看懂类图,才好说吗观察者在代码中的位置.但也要总结下观察者的消息事件对象: 1.观察者订阅某个主题: 2.主题发生变化,然后通知观察者 3.观察着收到通知,然后作出响应 这里涉及两类对象,观察者和被观察者(主题),首先第一步,观察者订阅某个主题,在业务领域,该行为动作应该由观察者自身发

浅谈ASP.NET Core中的DI

DI的一些事 传送门马丁大叔的文章 什么是依赖注入(DI: Dependency Injection)? ????依赖注入(DI)是一种面向对象的软件设计模式,主要是帮助开发人员开发出松耦合的应用程序.同时呢,让应用更容易进行单元测试和维护. ????DI其实就是用一个注入器类为一个对象提供其依赖的一个过程!如何更好的理解呢?下面就举个列子解释下! ????比如 class Client,它要使用服务class Service的提供的功能,这个时候就说Service是Client的依赖,程序实现

浅谈!SQL语句中LEFT JOIN ON WHERE和LEFT JOIN ON AND的区别

今天的工作学习之路是一个数据库的小知识,当时没有区分出所以然,特此记录分享一下子. 众所周知,数据库的表都是单独存在的,但是当我们进行联合查询(多表查询)时,我们获得数据库返回的值时就好像在一张表里一样,这是因为在进行联合查询时数据库会生成一个临时表返回给我们所想要的数据信息,这时我们都是通过LEFT JOIN 等语句进行相关联,并且我们也会为我们所想查询的数据进行一个筛选,这时我们就会用到过滤语句. LEFT JOIN ON WHERE:在临时表生成后,再对临时表的数据进行过滤,再返回左表.

浅谈java web开发中的乱码问题的解决

直接上在工作中遇到的问题吧: 在springmvc的项目中 前台表单通过get请求发送的中文在后台接收后出现乱码 于是我配置了一个spring的过滤器 org.springframework.web.filter.CharacterEncodingFilter 但是仅仅处理了post请求的中文乱码问题,网上说有一种简单的方法就是修改tomcat的server.xml文件,但是这个方法也太部靠谱了吧,还是另想他发吧! 于是我就着手写一个Filter去处理乱码问题 通过包装 javax.servle

浅谈python web框架中的orm设计

看了一下廖雪峰的那个web框架,其实就是封装了web.py,请求使用异步并将aiomysql做为MySQL数据库提供了异步IO的驱动,前端部分则整合了jinja.其中最难的应该是orm部分了. 下面是orm一个简单的例子. class User(Model): __table__ = 'users' id = StringField(primary_key=True, default=next_id, ddl='varchar(50)') email = StringField(ddl='var

【Unity游戏开发】浅谈Unity游戏开发中的单元测试

一.单元测试的定义与作用 单元测试定义:单元测试在传统软件开发中是非常重要的工具,它是指对软件中的最小可测试单元进行检查和验证,一般情况下就是对代码中的一个函数去进行验证,检查它的正确性.一个单元测试是一段自动化的代码,这段代码调用被测试的工作单元,之后对这个单元的单个最终结果的某些假设进行检验.单元测试使用单元测试框架编写,并要求单元测试可靠.可读并且可维护.只要产品代码不发生变化,单元测试的结果是稳定的.(百度的) 单元测试可以让你在软件开发的早期阶段发现 Bug,而不必到集成测试的时候才发