久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    [groovy]通過builder了解groovy的動態性

     chenge 2007-08-06





             

    Builder是Groovy相當有用的一個特性,樣例常常用生成XML來展現Builder所帶來的便利性,例如要生成下述的XML文檔:
    xml 代碼
     
    1. <books amount=‘2‘>  
    2.   <description>books to lean groovy<!--</span-->description>  
    3.   <book1 name=‘Groovy in Action‘ ISBN=‘1-932394-84-2‘ />  
    4.   <book2 name=‘Getting Started with Grails‘ ISBN=‘978-1-4303-0782-2‘ />  
    5. <!--</span-->books>   

    所使用的Groovy代碼是:
    import  groovy.xml.MarkupBuilder
     
    def xml = new MarkupBuilder()
     
    xml.books(amount:2) {
     description ‘books to lean groovy‘
     book1 (name:‘Groovy in Action‘, ISBN:‘1-932394-84-2‘)
     book2 (name:‘Getting Started with Grails‘, ISBN:‘978-1-4303-0782-2‘)
    }
     
    xml.println()
     
    從例子可以看到,在groovy中創建xml是相當的便利,你可以寫一個相應功能的java程序來對照。實際上這個groovy代碼結構跟所生成的html結果十分相似,從某種意義上來說,這像是在使用創建"BOOK XML"的專用的DSL了。
     
    我第一次看到這樣代碼的時候,心里很是疑惑,這是什么語法,為什么groovy自身的“groovy.xml.MarkupBuilder”類 會有books這個方法?慢慢了解其中的機制后,覺得builder真是groovy精華的集大成者,所謂“解脫之味不獨飲”,在此與朋友分享。
     
    1. groovy中是如何調用方法的?
     
    groovy基本上是兼容java語法的,但是為了更加方便開發人員,groovy作了許多便利的改進,比如說方法調用中省略括號
    description ‘books to lean groovy‘
    等同于
    description(‘books to lean groovy‘)
     
    所以在java中常用的打印語句
    System.out.println("Hello World!");
    可以簡寫為:
    println "Hello World!"
     
    同時調用方法的時候,傳遞參數可以加上參數的名字,例如
    def method1(String name, int age)
    的調用方式可以是:
    method1 (age:30, name:"Tom")
     
    而groovy方法調用中與我以前所接觸語言的最大不同就是Closure作為參數,而為了方便編寫代碼,一般也是將Closure寫在方法調用的最后,因此上述代碼的:
    xml.books(amount:2) {
    ...
    }
    等同于
    xml.books(amount:2, {...})
     
    這樣一來上述代碼的字面意思就明白了,是方法調用中包含Closure,Closure中又包含方法調用的混合體,不過用了groovy的特殊寫法。
     
    (注:關于groovy中方法調用的更詳細說明,請參考Groovy Statmements
     
    2. 無中生有的方法
     
    知道上述語句的字面意思后,但還是不知道為什么這些方法調用會成功呢,因為我們的代碼并沒有定義這些方法。
     
    在groovy中,所有的東西都是對象,而所有的對象都必須實現GroovyObject接口,該接口定義的方法不多,其中一個是:
    Object invokeMethod(String name, Object args)。
     
    原來在groovy中,編譯器會將所有的方法調用轉換成對invokeMethod的調用,例如:
    xml.books(amount:2) {
    ...
    }
    會轉換成
    xml.invokeMethod("books", list of parameters)
     
    groovy會將方法中的參數放入一個列表,作為invokeMethod()方法的第二個參數,invokeMethod()缺省實現將調用對象的同名函數,所以平時你對此是沒有察覺。
     
    也就是說MarkupBuilder不必事先定義books(), book1()這些方法,它可以假裝擁有這些方法,只需要在invokeMethod()的實現中根據name和args的值生成相應的xml代碼即可。
     
    實際上,在GroovyObject接口背后還有一個更加重要的MetaClass,從而使得groovy對象可以在運行時更改對象和類的行為,在groovy中可以輕易做到的有:
    1)假裝擁有某些方法,這就是MarkupBuilder干的,我覺得這一點在GPath中發揮的淋漓盡致!
    2)在語言級別支持Intercept模式
    3)將對自身方法的調用委派給其他對象完成(Delegate模式)
     
    3. 更加靈活的方法名
     
    注意到invodeMethod()的name參數是String類型,我第一個想法就是是否能夠用字符串來做方法名呢,例如:
    xml."books"(amount:2) {
    ...
    }
     
    實驗結果證實這樣的寫法是OK的,而因為groovy中字符串的特性,上述代碼還可以這么寫:
    import  groovy.xml.MarkupBuilder
     
    def xml = new MarkupBuilder()
    def names = [‘Groovy in Action‘, ‘Getting Started with Grails‘]
    def isbns = [‘1-932394-84-2‘, ‘978-1-4303-0782-2‘]
     
    xml.books(amount:names.size()) {
     description ‘books to lean groovy‘
     for(int i in 0..(names.size()-1)){
      def s = "book"+(i+1)
      "$s"(name:names[i],ISBN:isbns[i])
     }
    }
     
    xml.println()
     
    我最近在編寫一個數獨解題程序,就大大享受到字符變量做方法名的好處。因為在解題中往往要對“行/列”兩種情況都做一次,代碼結構基本一致,只 是多處調用的方法名和屬性名不同。在普通Java程序中,要將這樣的兩段代碼合并成一個方法少不了一大堆的if..then語句,而groovy只需要在 開頭設置好方法名即可,極為方便。
     
    4. 創建自己的builder
     
    如果你喜歡groovy builder這種模式,也可以創建自己builder,只要你的程序中存在用Builder模式可以解決的問題,groovy必然能幫上大忙,而且十分簡便、優雅。
     
    創建自己的builder也很簡單,只需要繼承BuilderSupport類,并實現其中幾個抽象方法包括:
    1)四種形式的createNode方法,groovy會根據你使用的形式自動調用相應的方法
    方法名 參數形式 使用樣例
    createNode Object name foo()
    createNode
    Object name, Object value
    foo(‘x‘)
    createNode Object name, Map attributes foo(a:1)
    createNode Object name, Map attributes, Object value foo(a:1, ‘x‘)
     
    2) void setParent(Object parent, Object child)
    設置樹狀繼承層次,當你創建子元素的時候,該方法就會被調用
     
    3)void nodeCompleted(Object parent, Object node)
    在子元素定義完畢后,該方法也會被自動調用。
     
    例如上述生成xml的代碼會被轉換成以下的調用方式:
    import  groovy.xml.MarkupBuilder
     
    def xml = new MarkupBuilder()
    def names = [‘Groovy in Action‘, ‘Getting Started with Grails‘]
    def isbns = [‘1-932394-84-2‘, ‘978-1-4303-0782-2‘]
     
    def books = xml.createNode(‘books‘, [amount:names.size()])
    def des = xml.createNode(‘description‘, ‘books to lean groovy‘)
    xml.setParent(books, des)
    xml.nodeCompleted(books, des)
    for(int i in 0..(names.size()-1)){
     def s = "book"+(i+1)
     def book = xml.createNode(s, [name:names[i],ISBN:isbns[i]])
     xml.setParent(books, book)
     xml.nodeCompleted(books, book)
    }
    xml.nodeCompleted(null, books)
     
    xml.println()
     
    在Groovy中令人感興趣的Builder還有:
    1)SwingBuilderGroovySWT,用于生成Swing/SWT界面,UI界面用Builder模式來產生是再合適不過的了。不過GroovySWT的發展似乎不如SwingBuilder好,在用戶郵件列表中常常提到SwingBuilder,而GroovySWT則好長時間沒有被人關注了。
     
    2)屬于Grails項目的Spring Bean Builder,通過Builder來編寫Spring的配置文件要比寫XML簡潔一百倍,而且更重要的是你可以很方便地在運行時動態生成Spring配置。
     
    通過這些精彩例子,相信你不難發現groovy builder能夠在你程序中大展身手的地方。
     
    這篇文章就到這里,希望我所描述的能夠引發你去了解groovy的興趣,groovy的確是個好東西!
     
     
    注:
    在本文中還有一個關鍵的地方沒有說明,就是Cloure中的方法調用
    {
      description ‘books to lean groovy‘
    }  
     
    為什么會觸發調用xml.createNode()方法?說明這個問題的主要關鍵有兩個:
    1)Closure中變量、方法的作用范圍,我們在Closure中能夠訪問到誰的變量、方法,為什么?
    2)Closure是如何將對自身方法的訪問“委派”給其他對象的?
    如果我夠勤奮的話,我會在另一篇blog討論這兩個問題 :)







      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 免费国产VA在线观看视频| 亚洲人妻一区二区精品| 福利一区二区在线视频| 国产成人综合欧美精品久久| 无码国模国产在线观看免费| 精品免费看国产一区二区| 在线中文字幕亚洲日韩2020| 中文有无人妻VS无码人妻激烈 | 免费人成在线观看网站| 中文字幕国产精品日韩| 国产成人亚洲精品无码电影不卡| 被公疯狂玩弄的年轻人妻| 影音先锋人妻啪啪AV资源网站| 福利一区二区1000| 亚洲一区二区三区影院| 国产在线中文字幕精品| 国产日产欧产精品精品| 中文字幕国产精品资源| 亚洲AV永久无码天堂网一线| 无套内谢少妇毛片在线| 四虎成人精品永久网站| 久久久久99精品国产片| 亚洲色成人一区二区三区| 亚洲精品无码国产片| 日本无遮挡吸乳视频| 2021国产成人精品久久| 国产成人AV一区二区三区在线| 色偷偷www.8888在线观看| 狠狠色噜噜狠狠狠狠AV| 欧美成人免费做真爱| 久久精品国产亚洲AV高清热| 亚洲AV永久无码精品秋霞电影影院| 日韩有码av中文字幕| 无码国产精品一区二区免费式影视| 欧美极品色午夜在线视频| 国产V亚洲V天堂A无码| 欧美孕妇变态孕交粗暴| 久久综合九色综合欧洲98| 起碰免费公开97在线视频| 18精品久久久无码午夜福利| 久女女热精品视频在线观看|