First they ignore you
          then they ridicule you
          then they fight you
          then you win
              -- Mahatma Gandhi
          Chinese => English     英文 => 中文             
          隨筆-221  評論-1047  文章-0  trackbacks-0
          利用Groovy與生俱來的動態特性,創建DSL(Domain Specific Language)是一件十分容易的事情。
          下面通過一個例子,向大家展示一下用Groovy創建DSL的優雅之處:

          利用下面這種語法
          ??? person {
          ??????? name {
          ??????????? firstname 'Daniel'
          ??????????? lastname? 'Sun'
          ??????? }
          ??? }

          ??? person {
          ??????? name {
          ??????????? firstname = '山風'
          ??????????? lastname? = '小子'
          ??????? }
          ??? }
          創建一個Person對象。

          def?createMetaClass(Class?clazz,?Closure?closure)?{
          ????
          /*?
          ????????為傳入的Class對象創建一個ExpandoMetaClass實例,但不將該ExpandoMetaClass實例注冊到MetaClassRegistry對象中
          ????
          */
          ????def?emc?
          =?new?ExpandoMetaClass(clazz,?false)?
          ????
          /*
          ????????該closure用來初始化ExpandoMetaClass對象,這種寫法的思想與Template?Method?Pattern有異曲同工之妙
          ????
          */
          ????closure(emc)?
          ????emc.initialize()?
          //?完成初始化過程
          ????return?emc
          }

          def?executeScript(dslScriptCode,?rootName,?closure)?{
          ????Script?dslScript?
          =?new?GroovyShell().parse(dslScriptCode)??//?讀取并解析DSL代碼,返回一個Script對象
          ????
          ????dslScript.metaClass?
          =?createMetaClass(dslScript.class)?{?emc?->
          ????
          /*
          ????????動態新增一個名為"$rootName"的方法,注意"$rootName"的值決定于運行時,比如本例中的值為person
          ????
          */
          ????????emc.
          "$rootName"?=?closure?
          ????}
          ????
          ????
          return?dslScript.run()?//?執行DSL代碼
          }

          class?Name?{
          ????String?firstname
          ????String?lastname
          ????String?toString()?{
          ????????
          "$firstname.$lastname"
          ????}
          }

          class?Person?{
          ????Name?name
          ????Person(name)?{
          ????????
          this.name?=?name
          ????}
          ????String?toString()?{
          ????????
          "My?name?is?$name"
          ????}
          }

          /*
          PersonDelegate對象是下面作為參數傳入‘person方法’的closure的delegate,形象點說,closure就是那對大括號{}以及大括號中的內容
          如果您對closure的delegate不太熟悉,可以參考在下的另一篇文章《Groovy解惑——closure中的delegate》(
          http://www.aygfsteel.com/BlueSUN/archive/2007/12/22/169580.html)
          ????person?{
          ????????
          ????}
          */
          class?PersonDelegate?{
          ????def?person
          ????PersonDelegate(person)?{
          ????????
          this.person?=?person
          ????}
          ????
          /*?
          ????????關于methodMissing這一特殊方法,請參考在下的另一篇文章《Groovy高效編程——動態改變對象的能力》(
          http://www.aygfsteel.com/BlueSUN/archive/2007/07/15/130318.html)
          ????
          */
          ????def?methodMissing(String?name,?Object?args)?{
          ????????
          if?('name'?==?name?&&?args[0]?instanceof?Closure)?{
          ????????????def?nameClosure?
          =?args[0]
          ????????????
          /*?
          ????????????????給nameClosure的delegate賦值,nameClosure就是name旁邊的那個closure即一對大括號{}以及大括號中的內容
          ????????????
          */
          ????????????nameClosure.delegate?
          =?new?NameDelegate(person)??
          ????????????nameClosure.resolveStrategy?
          =?Closure.DELEGATE_FIRST?//?指明closure中變量和方法的解析策略,本例選擇DELEGATE_FIRST
          ????????????nameClosure()
          ????????}
          ????}
          ????
          /*?
          ????????關于propertyMissing這一特殊方法,請參考在下的另一篇文章《Groovy高效編程——動態改變對象的能力》(
          http://www.aygfsteel.com/BlueSUN/archive/2007/07/15/130318.html)
          ????
          */
          ????def?propertyMissing(String?name)?{}
          }

          /*
          類似于PersonDelegate,
          NameDelegate對象是下面作為參數傳入‘name方法’的closure的delegate
          ????????name?{
          ????????????
          ????????}
          */
          class?NameDelegate?{
          ????def?person
          ????NameDelegate(person)?{
          ????????
          this.person?=?person
          ????}
          /*
          ????下面這些getter和setter是為了實現下面這種賦值而寫的:?firstname?=?'山風'和lastname??=?'小子'
          ????person?{
          ????????name?{
          ????????????firstname?=?'山風'
          ????????????lastname??=?'小子'
          ????????}
          ????}
          */
          ????def?getFirstname()?{
          ????????
          return?person.name.firstname
          ????}
          ????def?setFirstname(String?firstname)?{
          ????????person.name.firstname?
          =?firstname
          ????}
          ????def?getLastname()?{
          ????????
          return?person.name.lastname
          ????}
          ????def?setLastname(String?lastname)?{
          ????????person.name.lastname?
          =?lastname
          ????}
          ????
          ????def?methodMissing(String?name,?Object?args)?{
          ????????
          if?('firstname'?==?name)?{
          ????????????person.name.firstname?
          =?args[0]
          ????????}?
          else?if?('lastname'?==?name)?{
          ????????????person.name.lastname?
          =?args[0]
          ????????}
          ????}
          ????def?propertyMissing(String?name)?{}
          }

          /*
          ????在這篇文章中,演示了兩種賦值方式,各位可以根據自己的喜好選擇一種,我個人偏好第一種?:)
          */

          //?本例DSL的第一種寫法
          def?dslScriptCode?=?'''
          ????person?{
          ????????name?{
          ????????????firstname?
          'Daniel'
          ????????????lastname??
          'Sun'
          ????????}
          ????}
          '''

          def?scriptClosure?
          =?{?Closure?personClosure?->
          ????def?person?
          =?new?Person(new?Name())
          ????personClosure.delegate?
          =?new?PersonDelegate(person)
          ????personClosure.resolveStrategy?
          =?Closure.DELEGATE_FIRST
          ????personClosure()
          ????
          ????
          return?person
          }
          def?person?
          =?executeScript(dslScriptCode,?'person',?scriptClosure)

          println?person


          //?本例DSL的第二種寫法
          def?dslScriptCode2?=?'''
          ????person?{
          ????????name?{
          ????????????firstname?
          =?'山風'
          ????????????lastname??
          =?'小子'
          ????????}
          ????}
          '''

          def?scriptClosure2?
          =?{?Closure?personClosure?->
          ????def?person2?
          =?new?Person(new?Name())
          ????personClosure.delegate?
          =?new?PersonDelegate(person2)
          ????personClosure.resolveStrategy?
          =?Closure.DELEGATE_FIRST
          ????personClosure()
          ????
          ????
          return?person2
          }
          def?person2?
          =?executeScript(dslScriptCode2,?'person',?scriptClosure2)

          println?person2


          運行結果:
          My?name?is?Daniel.Sun
          My?name?is?山風.小子

          附:朝花夕拾——Groovy & Grails
          posted on 2008-05-17 00:38 山風小子 閱讀(5713) 評論(1)  編輯  收藏 所屬分類: Groovy & Grails

          轉載文章,請保留原始鏈接和署名



          Dict.CN
          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(71)

          隨筆分類

          隨筆檔案

          相冊

          Documentations

          Groovy & Grails

          友情鏈接

          好友 & 鄰居

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 796531
          • 排名 - 52

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 南阳市| 周至县| 千阳县| 苏州市| 丹棱县| 南京市| 正安县| 龙海市| 仪陇县| 泽库县| 沙雅县| 探索| 汉沽区| 建昌县| 襄垣县| 定兴县| 泽州县| 乌海市| 荃湾区| 清镇市| 唐河县| 栾城县| 哈巴河县| 绵阳市| 诏安县| 浑源县| 新竹县| 松阳县| 哈巴河县| 大新县| 华亭县| 招远市| 左贡县| 大兴区| 汝州市| 鹤峰县| 遂宁市| 壤塘县| 库伦旗| 永和县| 方山县|