Groovy探索之閉包 六 探索閉包的應用是一件很有意思的事,它的有意思在于我們永遠不知道有哪些地方不能應用到閉包,或者說在每一個角落,你都能找到閉包讓人眼睛一亮的應用。今天到談到的是閉包的有關于DSL的應用。DSL應該是這兩年才興起的一個概念,有關它的一些知識,請查閱相關文檔。 DSL的優越性在于它的接近自然語言,以及它的編碼的友善和快捷。而閉包天生能夠展現DSL的這些優越性,是以,它被選做DSL的一種實作就不足為奇了。 下面試着舉出幾個例子來說說閉包在這方面的應用。 比如,有一個公司的人事管理有這樣的一些規定:員工每個月遲到3次會怎麼,早退三次會怎麼,請假三次又會怎麼,等等,等等。 在實作這樣的一個功能的時候,我們把員工的出勤記錄分為這樣的一些狀态:“O”代表按時出勤;“L”代表遲到;“H”代表請假;“E”代表早退。 我們有一個TimeLog的類為員工做出勤記錄: class TimeLog { String id String name String[] states } 假設一個員工的出勤記錄是這樣的: def timelog = new TimeLog(id: '123' ,name: 'tom' ) def states = [ 'O' , 'L' , 'E' , 'O' , 'L' , 'H' , 'H' , 'H' , 'O' , 'O' , 'O' , 'O' , 'L' , 'L' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' , 'O' ] timelog.states = states 應用閉包,我們可以寫出如下的代碼來: def IfThreeTimes = { state,timeLog,Closure closure -> int i = 0 for (tl in timeLog.states) { if (tl == state&&i == 3 ) { closure. call () break } else if (tl == state ) { i++ } } } 閉包名為“IfThreeTimes”,意思是“如果三次了”,很好了解。它的參數有“state”,代表的是狀态,是什麼三次了,遲到還是請假。“timeLog”是某一個員工的出勤記錄。最後一個參數是一個閉包,“closure”指的是三次了以後要怎麼處理,可能的處理有:扣工資,沒有獎金,不能評優秀等等。 具體到如果我們要處理遲到的問題,我們可以使用curry方法再做一次抽象,代碼如下所示: def IfThreeTimesLate = IfThreeTimes.curry( 'L' ) 最後,我們來測試我們的 DSL : IfThreeTimesLate(timelog){ println 'You will lose money' } 結果為: You will lose money 做這樣的DSL編碼是不是很有意思。下面再來看一個例子。 公司有各種各樣的申請,如“請假申請”,“部門調動申請”,“求職申請”等等,這些申請都由相關人員進行準許或否決。 如請假申請類: class Holiday { String id String name String beginDate String endDate String reason boolean approved } 下面還有一個求職申請類: class Offer { String name String reason boolean approved } 由上面的需求,我們可以建立如下的閉包: def IfApproved = { which,Closure closure -> if (which.approved) { closure. call () } } 參數“which”是需要輸入哪一種申請;同樣,參數“closure”代表如果申請成功了的話,要做些什麼。 def holiday = new Holiday(id: '123' ,name: 'tom' ,approved: false ) def offer = new Offer(name: 'mike' ,approved: true ) IfApproved(holiday) { println 'You will have a holiday' } IfApproved(offer) { println 'good, your offer is approved' } 運作結果為: good, your offer is approved 這個例子,除了使用到閉包,還使用到Groovy語言的動态特性,共同完成了這樣一個DSL的編寫。 上面的例子都很小,也很簡單,但是能夠幫助我們整理閉包在DSL方面的應用,我用來借以抛磚引玉,使得我們能夠在今後的應用中寫成更好的DSL來。