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

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

          ??? person {
          ??????? name {
          ??????????? firstname = '山風(fēng)'
          ??????????? lastname? = '小子'
          ??????? }
          ??? }
          創(chuàng)建一個(gè)Person對(duì)象。

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

          def?executeScript(dslScriptCode,?rootName,?closure)?{
          ????Script?dslScript?
          =?new?GroovyShell().parse(dslScriptCode)??//?讀取并解析DSL代碼,返回一個(gè)Script對(duì)象
          ????
          ????dslScript.metaClass?
          =?createMetaClass(dslScript.class)?{?emc?->
          ????
          /*
          ????????動(dòng)態(tài)新增一個(gè)名為"$rootName"的方法,注意"$rootName"的值決定于運(yùn)行時(shí),比如本例中的值為person
          ????
          */
          ????????emc.
          "$rootName"?=?closure?
          ????}
          ????
          ????
          return?dslScript.run()?//?執(zhí)行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對(duì)象是下面作為參數(shù)傳入‘person方法’的closure的delegate,形象點(diǎn)說(shuō),closure就是那對(duì)大括號(hào){}以及大括號(hào)中的內(nèi)容
          如果您對(duì)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
          ????}
          ????
          /*?
          ????????關(guān)于methodMissing這一特殊方法,請(qǐng)參考在下的另一篇文章《Groovy高效編程——?jiǎng)討B(tài)改變對(duì)象的能力》(
          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旁邊的那個(gè)closure即一對(duì)大括號(hào){}以及大括號(hào)中的內(nèi)容
          ????????????
          */
          ????????????nameClosure.delegate?
          =?new?NameDelegate(person)??
          ????????????nameClosure.resolveStrategy?
          =?Closure.DELEGATE_FIRST?//?指明closure中變量和方法的解析策略,本例選擇DELEGATE_FIRST
          ????????????nameClosure()
          ????????}
          ????}
          ????
          /*?
          ????????關(guān)于propertyMissing這一特殊方法,請(qǐng)參考在下的另一篇文章《Groovy高效編程——?jiǎng)討B(tài)改變對(duì)象的能力》(
          http://www.aygfsteel.com/BlueSUN/archive/2007/07/15/130318.html)
          ????
          */
          ????def?propertyMissing(String?name)?{}
          }

          /*
          類似于PersonDelegate,
          NameDelegate對(duì)象是下面作為參數(shù)傳入‘name方法’的closure的delegate
          ????????name?{
          ????????????
          ????????}
          */
          class?NameDelegate?{
          ????def?person
          ????NameDelegate(person)?{
          ????????
          this.person?=?person
          ????}
          /*
          ????下面這些getter和setter是為了實(shí)現(xiàn)下面這種賦值而寫的:?firstname?=?'山風(fēng)'和lastname??=?'小子'
          ????person?{
          ????????name?{
          ????????????firstname?=?'山風(fēng)'
          ????????????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)?{}
          }

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

          //?本例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?
          =?'山風(fēng)'
          ????????????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


          運(yùn)行結(jié)果:
          My?name?is?Daniel.Sun
          My?name?is?山風(fēng).小子

          附:朝花夕拾——Groovy & Grails
          posted on 2008-05-17 00:38 山風(fēng)小子 閱讀(5702) 評(píng)論(1)  編輯  收藏 所屬分類: Groovy & Grails
          主站蜘蛛池模板: 淮滨县| 徐汇区| 洮南市| 平江县| 荥阳市| 营口市| 乐昌市| 浦江县| 曲靖市| 九龙城区| 永安市| 仁化县| 桐梓县| 图片| 贡山| 平陆县| 禹城市| 祁东县| 公安县| 湖口县| 卫辉市| 崇义县| 禹州市| 乌兰察布市| 嵊州市| 牙克石市| 迁安市| 琼结县| 茌平县| 澎湖县| 习水县| 卓资县| 海丰县| 通河县| 绵阳市| 吉木萨尔县| 托里县| 额济纳旗| 衡阳县| 饶平县| 佛山市|