程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Groovy >> Groovy探索之閉包 一

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探索之閉包》的第一篇,我們暫時談到這裡。上面的例子可能有人覺得毫無意義,沒有太大的用處,但是我舉出這些例子是為了提供一些使用閉包的思路,並不見得實際編碼過程中就要這樣用。

閉包還有很多有趣的、方便快捷的使用方法。我們會在後續的文字中一一道來。

  1. 上一頁:
  2. No
Copyright © 程式師世界 All Rights Reserved