乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      [groovy]通過builder了解groovy的動態(tài)性

       chenge 2007-08-06





               

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







        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多