Groovy語言最引以為豪的特點就是DSL了,關於DSL的定義以及分類、優點等,就不是本篇所要闡述的了,大家可以上網查,網上有大量的這方便的介紹。Groovy語言是非常便於設計內部DSL了,在這方面,我的Groovy探索系列已經有了很多專題談到過使用Groovy語言創建內部DSL的一些方面。本篇所要探索的是一個關於Groovy語言DSL的一個非常小的方面、也是非常不起眼的方面:關於方法名的DSL。
說到方法名的DSL,其實我們在Groovy語言中已經有了非常廣泛的應用。比如,我們在一開始學習Groovy語言,就會寫一個“HelloWorld”的程序來開始我們的第一個Groovy語言程序,它的代碼大致如下:
public class HelloWorld{
/**
* @param args
*/
public static void main(def args){
// TODO Auto-generated method stub
println 'Hello,World!'
}
}
它的運行結果就不要我多說了。我們感興趣的是“println”方法,我們都知道,在Java語言中,該對應的方法是“System.out.println”。將長的方法名——“System.out.println”寫成了“println”,就是Groovy語言中關於方法的DSL的一個應用。這樣的好處主要是兩個方面:第一是編碼的快捷性增加,輸入“println”當然也輸入“System.out.println”方便了很多;第二就是可讀性的增強,這是DSL的追求,“println”的可讀性也比“System.out.println”強。
那麼,我們在實際的編碼過程中,又該如何實現形如“println”這樣的DSL呢?
關於方法名的DSL,在Groovy語言中,有三種實現方法,先說其中的兩種,它們分別是靜態引入和使用“as”關鍵字。我們還是以一個例子來說明。
比如,我們想取得系統的當前時間,Java語言的方式是如下的:
System.out.println(System.currentTimeMillis())
有了靜態引入,我們在Groovy語言中的編碼將是這樣的:
import static System.currentTimeMillis
/**
* @author Administrator
*
*/
public class Testor2{
/**
* @param args
*/
public static void main(def args){
// TODO Auto-generated method stub
println currentTimeMillis()
}
}
當然,我們還可以更進一步,使用“as”關鍵字的代碼則會是這樣的:
import static System.currentTimeMillis as now
/**
* @author Administrator
*
*/
public class Testor2{
/**
* @param args
*/
public static void main(def args){
// TODO Auto-generated method stub
println now()
}
}
這樣,我們就更加DSL了,“now”方法很形象的告訴我們要取的是現在的時間,這樣就更有DSL的意味了。
知道了這兩中實現DSL方法的使用,我們就可以廣泛的使用到它們,比如,我們在Groovy語言的編碼過程中,使用到了舊的Java包或庫,裡面所有的靜態方法,都可以這樣用,用來簡化我們的編碼,方便我們的理解。同時,我們自己的工具包,我們定義的很多靜態工具方法,也都可以這樣使用。
第三種方法就是定義閉包來實現DSL,提高代碼的可讀性。我們還是以一個簡單的例子來說明。
我們現在來模擬某個網上購物程序,現在我們有如下的一個商品類,用來模擬擺在網上買賣的商品:
public class Goods{
String no
String name
float price
int count
}
為了示例的簡單,我們盡量簡化了這個商品類,只有四個屬性:商品的編碼、商品名稱、商品單價以及購買的數量。
下面是我們的購買者賬戶類:
public class Account{
String code
String name
def goodses
def Account(code,name)
{
this.code = code
this.name = name
this.goodses = []
}
def buy(Goods goods)
{
this.goodses << goods
}
def view()
{
this.goodses.each
{
println "${it.name}"
}
}
}
它也很簡單,只有兩個屬性,用戶編碼和姓名。後面有兩個方法,“buy”方法用來完成買商品的動作,而“view”用來查看買了哪些商品。
下面,我們就可以來測試它們。我們先實例化一個賬戶,然後實例化她要買的幾件商品,如下:
def account = new Account('09833','Tom')
def knife = new Goods(no:'1001',name:'knife')
def flower = new Goods(no:'1022',name:'flower')
接著,我們來定義一個可讀性好的閉包,如下所示:
def buy = account.&'buy'
這就是我們的一種DSL的實現方法,下面我們就可以使用這個DSL,如下:
buy knife
buy flower
我們的賬戶買了兩件商品,分別是小刀和鮮花,“buy knife”和“buy flower”,看起來多好的閱讀性啊!
這就是DSL的效果。
當然,我們接著還有些測試代碼,來查看我們所買的商品是否買到了:
println "dear ${account.name},you have bought: "
def view_goods = account.&view
view_goods()
運行結果為:
dear Tom,you have bought:
knife
flower
好了,最後總結一下:在Groovy語言中,我們有三種方法來實現有關方法名的DSL,分別是:靜態引入、使用“as”關鍵字和定義可讀性的閉包。
最後,值得注意的是,我上面關於靜態引入的代碼,是在Groovy1.5以上的版本運行成功的,而Groovy1.0版本是不能編譯靜態引入的代碼的。