Builder是Groovy相当有用的一个特性,样例常常用生成XML来展现Builder所带来的便利性,例如要生成下述的XML文档:
xml 代码
- <books amount='2'>
- <description>books to lean groovy<!---->description>
- <book1 name='Groovy in Action' ISBN='1-932394-84-2' />
- <book2 name='Getting Started with Grails' ISBN='978-1-4303-0782-2' />
- <!---->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的特殊写法。
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必然能帮上大忙,而且十分简便、优雅。
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)
SwingBuilder和
GroovySWT,用于生成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讨论这两个问题 :)
分享到:
- 2007-08-05 23:59
- 浏览 4031
- 评论(4)
- 论坛回复 / 浏览 (3 / 5888)
- 查看更多
相关推荐
2. **动态性与灵活性**:Groovy的动态特性允许在运行时进行代码修改,这对于原型设计和快速迭代开发尤其有利。 3. **集成Eclipse生态**:由于EMF是Eclipse的一部分,Groovy EMF Builder可以无缝地融入Eclipse IDE,...
- **Builder模式**:Groovy通过Builder模式简化了XML和其他结构化数据的生成。 - **GDK(Groovy Development Kit)**:GDK扩展了Java类库的功能,为常见任务提供了更简洁的API。 - **数据库编程**:Groovy提供了...
Groovy提供了大量的动态特性,比如动态类型、闭包、元编程能力等,使得编写脚本或应用程序变得更加高效和愉悦。Groovy是完全兼容Java的,这意味着Java开发人员可以轻松地使用Groovy编写程序,并利用Groovy提供的强大...
这部分内容深入探讨了Groovy如何通过动态类型和元编程支持动态对象导向编程。 ### Groovy库的应用 #### 工作于建造者 Groovy提供了一种名为Builder的模式,用于简化XML和HTML等格式的文本生成,这部分内容介绍了...
Groovy是一种基于Java平台的、动态的、面向对象的编程语言,它被广泛用于脚本编写、自动化任务、测试等领域。在Groovy中发送HTTP请求是开发者经常需要进行的操作,尤其是在进行API测试或者集成第三方服务时。下面...
### Groovy and Grails ...通过这些章节的学习,读者将能够全面了解Groovy编程语言和Grails框架,并掌握如何使用它们来开发高效、可维护的应用程序。无论是新手还是有经验的开发者,都能从中获得宝贵的知识和实践经验。
《Groovy User Guide》为开发者提供了一个全面了解 Groovy 的机会,无论是对于初学者还是有经验的开发者都非常有用。通过学习这份文档,开发者可以更好地掌握 Groovy 的特性和功能,并将其应用于实际项目中。此外,...
Groovy是一种基于Java平台的动态语言,它在Java生态系统中常用于快速开发和脚本编写。 1. **Groovy语言基础**: - Groovy是JVM上的一个开源语言,语法简洁,支持面向对象、函数式编程。 - 它兼容Java代码,可以...
Groovy是一种基于JVM的动态编程语言,它简化了Java的语法并增加了许多便利特性。Groovy的RESTClient库是一个强大的工具,用于发送HTTP请求并处理响应,这对于与CouchDB进行交互非常实用。RESTClient库支持GET、POST...
- **学习目标**: 理解Groovy动态特性的原理,能够利用这些特性来构建更灵活的应用程序。 **第8章: Working with Builders** - **内容概述**: 介绍Groovy中的构建器(builder)机制,这是一种高效的数据结构创建方式...
Groovy是一种面向对象的、动态类型的Java平台语言,它的语法简洁,支持闭包和DSL(领域特定语言)构造,这使得Groovy成为创建自定义构建器的理想选择。`YangBuilder` 就是利用了Groovy的这些特性,让YANG模型的编写...
1. 支持Groovy语法,提供动态类型的灵活性。 2. 提供了一个交互式的命令行界面,方便调试和测试。 3. 可以轻松执行Java类库中的方法,便于与现有的Java项目集成。 4. 内置了对脚本控制流、字符串操作和集合处理的...
根据给定的文件信息,我们可以提炼...通过以上分析,我们可以看到SpringOne2GX2010大会不仅回顾了Groovy的发展历程,还展望了其未来的方向,展示了Groovy作为一种动态语言如何持续进化,以适应不断变化的软件开发需求。
Groovy是一种基于Java平台的动态编程语言,它具有简洁的语法和强大的功能,常用于构建脚本和快速原型开发。在创建网络爬虫时,Groovy可以利用其与Java的互操作性,利用如Jsoup或Apache HttpClient等库来解析HTML和...
在Java编程中,URL(Uniform Resource Locator)是用于定位网络资源的重要工具。本文将深入探讨Java中常见的URL...同时,对于Groovy或其他库的使用,了解其对URL处理的方式也非常重要,以确保代码的健壮性和兼容性。
本文将详细介绍如何通过一个名为RetrofitUrlManager的库,以最简洁的API实现Retrofit支持多个BaseUrl以及动态改变BaseUrl的功能。 首先,了解RetrofitUrlManager。这是一个由JessYan编写的开源库,专门为Retrofit...
#### 知识点解析 **一、项目概述** **IBM Project ZERO** 是IBM推出的一个全新的企业级应用...通过对本书的学习,开发者不仅可以掌握如何使用Project ZERO进行高效开发,还能了解到最新的Web技术趋势和发展方向。
Groovy是一种动态、灵活的编程语言,它在Java平台上运行,并与Java紧密集成。这个名为“图书馆”的项目可能是一个使用Groovy...通过Groovy的灵活性和简洁性,开发者可以高效地创建和维护一个功能完备的图书馆管理系统。