Groovy探索之闭包 一

                                        Groovy探索之闭包 一
 
动态语言的闭包是一个永恒的话题。闭包在编码过程的方便和快捷使得动态语言的拥护者对它津津乐道,而静态语言特别是Java语言的扇子们会拿出匿名内部类来说Java语言也有类似的功能。我使用Java语言至今也有六七年的时间了,实话来说我也很喜欢Java语言,但我万万不敢拿Java语言的匿名内部类和闭包来对比。因为匿名内部类的隐晦和繁琐,使得我在编码的过程中很少使用它,怎么敢拿它出来吹嘘呢?而在我使用Groovy编码的不到一年的过程中,我却时时刻刻在使用闭包。
闭包实在是太方便和灵活了,使得我在使用它的时候信手拈来。在我看来,闭包就像Groovy等动态语言给我们的一道鱼翅大餐。这道大餐的好处需要我们慢慢的一一道来,记得星爷的《济公》里有一句台词:来碗鱼翅嗽嗽口。不错,今天我们先要说说闭包在Groovy编码过程中随处可用小用法,权当使用闭包这碗鱼翅来嗽嗽口。
温馨提示,阅读本文需要您有闭包的基础知识。例如,关于闭包的定义及调用;闭包的参数、变量和返回值的作用域等一些简单的基础知识。当然,您也可以试着在阅读本文的时候,同时把上述的基础知识一并找来看,借此来相互理解和相互支持。对闭包基础阐述得最清楚的书籍是《Groovy in Action》
一.小试身手,随处可用
Java语言的编码过程中,有随处可见的我们用起来觉得别扭的地方,却又无计可施。例如,我们经常要对一系列的String进行非空判断以后再进行操作:
if(str1!=null&&!str1.trim().equals(“”))
{
        ……
}
if(str2!=null&&!str2.trim().equals(“”))
{
        ……
}
if(str3!=null&&!str3.trim().equals(“”))
{
        ……
}
……
这样反复的if判断真让人忍无可忍,但是你没有好的解决办法,只能这样五个、六个甚至十个的写下去。
Stop!我们来考虑一下闭包的解决方案吧。
来,我们先定义一个闭包,很简单。
def isNotNull = {
        str,Closure closure ->
              if(str!=null&&!str.trim().equals(""))
              {
                 closure.call()
              }
 }
很普通的一个闭包,两个输入参数,如果没明白的话,现在就翻出闭包的基础知识看一看。
简单的闭包定义好了以后,我们就可以开始使用它了:
def abc = 'abc'
     isNotNull(abc)
     {
        println abc
 }
在上面的例子中,我们小试牛刀了一次,只是判断了一下字符串abc是否为空,如果不为空就打印到控制台。比起我们上面的if语言,是不是简洁多了。
像这样的用法,我们在编码的过程中随处可见,下面再举一个例子:
       String cateType = getRequest().getParameter("cateType");//1: 确认存储 2:反确认
       String cateId = getRequest().getParameter("cateId");
       String year = getRequest().getParameter("year");
    String percent = getRequest().getParameter("percent");
不错,这是一段获取request参数的代码。我们在写这样的代码的时候,多了就会郁闷,我老是先要getRequest然后getParameter重复的同样的锻炼我们的盲打能力。
Stop!我们来使用闭包减轻我们的打字频率吧。
同样,先是定义一个闭包:
     def getReqParam = {
            paramName ->
             return getRequest().getParameter(paramName)
 }
那么,上面的代码,我们可以写成下面的样子:
String cateType = getReqParam("cateType");//1: 确认存储 2:反确认
       String cateId = getReqParam("cateId");
       String year = getReqParam("year");
    String percent = getReqParam("percent");
怎么样,是不是简洁多了?
 
二.神来之笔
除了上面的一些小用法,闭包的灵活性在编码的过程中随时可能显示出来。你会在Java编程过程中随时找到一些对闭包的妙用。
比如,我们在编码的过程中,随时会做一些log记录。
    logger.debug("importPartList condition:");
logger.debug("userid=" + excelModel.getUserid());
这样的log是我们常用的,但鉴于性能方面的要求,我们实际上不会直接打印log,而是首先判断log的开关状态。如下:
       if (logger.isDebugEnabled()) {
           logger.debug("isPPRMBuyer=" + isPPRMBuyer);
    }
下面的一小段代码就是这样一个场景。
       if (logger.isDebugEnabled()){
           logger.debug("updateAfterUploadRaw start:");
       }
      
       ret = (String)dao.getObjectByStoredProcedure(
              "updateBuyerCRDetail",
              map,
              new String[]{"v_matetype"},
              OracleTypes.VARCHAR);
       if (logger.isDebugEnabled()){
           logger.debug("1. updateBuyerCRDetail result ret=" + ret);
       }     
       if(!ret.equals("0"))
       {
           errMsg += "Update Buyer管控總表 failed! ";
       }
      
       ret = (String)dao.getObjectByStoredProcedure(
              "updateBuyerCRDetailYt",
              map,
              new String[]{"v_matetype"},
              OracleTypes.VARCHAR);
      
       if (logger.isDebugEnabled()){
           logger.debug("2. updateBuyerCRDetailYt result ret=" + ret);
    }
可以看到,就是上面的一小段代码,却已经使用了三个if (logger.isDebugEnabled())
这样重复使用的判断语句让我们在编码的过程中相当郁闷,可能有很多人想把它抽象成下面的一个方法:
    publicstaticvoid debug(logger,String str)
    {
       if(logger.isDebugEnabled())
        {
           logger.debug(str);
       }
}
这样使用使用固然是方便了很多,但却违背了我们使用该判断语句的初衷,即不能解决性能方面的问题。
显然,这不是一个好的解决方法。
现在,我们来看看闭包的解决方法:
     def isdebuged = {
            Closure closure ->
             if(logger.isDebugEnabled())
             {
                  closure.call();
             }
 }
使用这个闭包,上面的那一小段代码就变成下面的样子:
       isdebuged {
           logger.debug("updateAfterUploadRaw start:");
       }
      
       ret = (String)dao.getObjectByStoredProcedure(
              "updateBuyerCRDetail",
              map,
              new String[]{"v_matetype"},
              OracleTypes.VARCHAR);
       isdebuged {
           logger.debug("1. updateBuyerCRDetail result ret=" + ret);
       }     
       if(!ret.equals("0"))
       {
           errMsg += "Update Buyer管控總表 failed! ";
       }
      
       ret = (String)dao.getObjectByStoredProcedure(
              "updateBuyerCRDetailYt",
              map,
              new String[]{"v_matetype"},
              OracleTypes.VARCHAR);
      
       isdebuged {
           logger.debug("2. updateBuyerCRDetailYt result ret=" + ret);
    }
这样,我们就可以从写if判断语句中解脱出来。
好了,作为系列《Groovy探索之闭包》的第一篇,我们暂时谈到这里。上面的例子可能有人觉得毫无意义,没有太大的用处,但是我举出这些例子是为了提供一些使用闭包的思路,并不见得实际编码过程中就要这样用。
闭包还有很多有趣的、方便快捷的使用方法。我们会在后续的文字中一一道来。
 
 
展开阅读全文

没有更多推荐了,返回首页