DSL的基本介绍(groovy来进行构建)

什么是DSL?

领域特定语言,针对一个特定的领域,具有受限表达性的一种计算机程序语言。可以看做是一种抽象处理的方式。

具有四个元素,第一个是计算机程序设计语言,使用DSL来指挥计算机做事情,语言性(一种特定的语言),受限的表达性,并不像同通用的设计语言那样具有广泛的能力,针对一个明确的领域。

分类有哪些?

外部DSL:不同于应用系统主要使用语言的语言,通常采用自定义语法,宿主应用的代码采用文本解析技术对外部DSL编写的脚本进行解析。例子如:正则表达式、SQL、AWK以及Struts的配置文件等

内部DSL:通用语言的特定语法,用内部DSL写成的脚本是一段合法的程序,但是它具有特定的风格,而且仅仅用到了语言的一部分特性,用于处理整个系统一个小方面的问题;

语言工作台:一种专用的IDE,用于定义和构建DSL,具体的讲,语言工作台不仅用来确定DSL的语言结构,而且是人们编写DSL脚本的编辑环境,最终的脚本讲编辑环境和语言本身紧密的结合在一起;

为什么需要DSL?

1、提高开发效率,通过DSL来抽象构建模型,抽取公共的代码,减少重复的劳动;

2、和领域专家沟通,领域专家可以通过DSL来构建系统的功能;

3、执行环境的改变,可以弥补宿主语言的局限性;

DSL的处理可能包含那几个步骤?

1、DSL脚本;

2、解析脚本;

3、语义模型;

4、生成代码或者执行模型;

为啥groovy能比较好的构建DSL?

1、不需要class文件,可以直接执行脚本;

2、闭包等特性以及语法的简介,使用非常灵活;

3、可以和java系统无缝的整合;

4、Groovy自身不是 DSL。 Groovy官方已经发布了较多基于 Groovy书写的 DSL,比如 GANT, GORM, XMLBuilder, HtmlBuilder等等;

使用groovy做DSL的例子?

1、一个自定义的dsl,例如这个:

1
2
3
4
5
6
7
8
ParseDsl.make {
                 to  "Nirav Assar"
                 from  "Barack Obama"
                 body  "How are things? We are doing well. Take care"
                 idea  "The economy is key"
                 request  "Please vote for me"
                 xml
             }

2、那必须要有地方解析这个规则:

//groovy methodMissing如果找不到方法,就会调用这个方法 里面用到了这个特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import  groovy.xml.MarkupBuilder;
/**
* 解析一个自定义的DSL文本的类,类似解析规则
*/
class  ParseDsl {
 
     String toText
     String fromText
     String body
     def  sections = []
 
     
     def  static  make(closure) {
         ParseDsl memoDsl =  new  ParseDsl()
         closure.delegate = memoDsl
         closure()
     }
 
     def  to(String toText) {
         this.toText = toText
     }
 
     def  from(String fromText) {
         this.fromText = fromText
     }
 
     def  body(String bodyText) {
         this.body = bodyText
     }
 
     def  methodMissing(String methodName, args) {
         def  section =  new  Section(title: methodName, body: args[ 0 ])
         sections << section
     }
 
     def  getXml() {
         doXml(this)
     }
 
     def  getHtml() {
         doHtml(this)
     }
 
     def  getText () {
         doText(this)
     }
 
     private  static  doXml(ParseDsl memoDsl) {
         def  writer =  new  StringWriter()
         def  xml =  new  MarkupBuilder(writer)
         xml.memo() {
             to(memoDsl.toText)
             from(memoDsl.fromText)
             body(memoDsl.body)
             for (s  in  memoDsl.sections) {
                 "$s.title" (s.body)
             }
         }
         println  writer
     }
 
     private  static  doHtml(ParseDsl memoDsl) {
         def  writer =  new  StringWriter()
         def  xml =  new  MarkupBuilder(writer)
         xml.html() {
             head {
                 title( "Memo" )
             }
             body {
                 h1( "Memo" )
                 h3( "To: ${memoDsl.toText}" )
                 h3( "From: ${memoDsl.fromText}" )
                 p(memoDsl.body)
                 for (s  in  memoDsl.sections) {
                     p {
                         b(s.title.toUpperCase())
                     }
                     p(s.body)
                 }
             }
         }
         println  writer
     }
 
     private  static  doText(ParseDsl memoDsl) {
         String template =  "Memo\nTo: ${memoDsl.toText}\nFrom: ${memoDsl.fromText}\n${memoDsl.body}\n"
         def  sectionStrings = ""
         for (s  in  memoDsl.sections) {
             sectionStrings += s.title.toUpperCase() +  "\n"  + s.body +  "\n"
         }
         template += sectionStrings
         println  template
     }
}

 

关于groovy中的闭包?

http://docs.codehaus.org/pages/viewpage.action?pageId=167477326

groovy中的闭包是一个匿名的代码块,可以接受参数,并返回一个返回值,也可以引用和使用在他周围的,可见域中定义的变量。Groovy 之所以包含闭包,是因为它可以让开发者写出更简约、更易懂的代码。Java 开发者通常用一个单方法的接口(Runable,采用Command设计模式),并结合匿名内部类来实现;而Groovy 则允许以一种更简易、直白的方式来实现。额外的,相较匿名内部类,闭包有很少量的约束,包括一些额外的功能。

例子代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//第一个例子
def  shout = {src->
         return  src.toUpperCase()
     }
  println  shout( "Hello World" )
  
  //模拟一个for循环的例子,在List的循环中添加Closure
  def  names = [ "alibaba-inc.com" , "bixiao.zy" , "hello world" , "iamzhongyong" ]
  printInfo = {
      println  "hello,${it},welcome"
  }
  names. each  printInfo
  
  //Colsure作为方法的入参
  def  closureMethod(Closure c) {
      c.call( "iamzhongyong" )
}
closureMethod { name->
      println  "Closure called " +name
}
 
//为参数提供默认值
greetString = { greet,name =  "iamzhongyong"  ->
     return  "${greet},${name}"
}
assert  greetString( "welcome" ) ==  "welcome,iamzhongyong"
assert  greetString( "hello" , "bixiao.zy" ) ==  "hello,bixiao.zy"
 
//使用闭包实现单方法接口
interface  Test {
     def  one()
}
def  test = { println  'one' as  Test
test.one()
 
//使用闭包实现多方法接口
interface  Test {
     def  one()
     def  two()
}
def  test = [
     one: { println  'one' },
     two: { println  'two' }
     as  Test
test.one()
test.two()

lambda和闭包(closure)的区别是什么

lambda就是匿名函数——即没有名字的函数。前面你已经看到过一些例子了。闭包就是封闭在其定义所处环境的任意函数。

 

http://lggege.iteye.com/blog/543730

http://docs.codehaus.org/pages/viewpage.action?pageId=167477326

http://groovy.codehaus.org/Builders

http://confluence.jetbrains.com/display/GRVY/Scripting+IDE+for+DSL+awareness

http://java.dzone.com/articles/groovy-dsl-simple-example

 

 

 

猜你喜欢

转载自iamzhongyong.iteye.com/blog/2025638