浏览 5882 次
精华帖 (0) :: 良好帖 (4) :: 新手帖 (0) :: 隐藏帖 (0)
|
||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | |||||||||||||||||||||||||
发表时间:2007-08-05
Builder是Groovy相当有用的一个特性,样例常常用生成XML来展现Builder所带来的便利性,例如要生成下述的XML文档:
xml 代码
所使用的Groovy代码是:
从例子可以看到,在groovy中创建xml是相当的便利,你可以写一个相应功能的java程序来对照。实际上这个groovy代码结构跟所生成的html结果十分相似,从某种意义上来说,这像是在使用创建"BOOK XML"的专用的DSL了。
我第一次看到这样代码的时候,心里很是疑惑,这是什么语法,为什么groovy自身的“groovy.xml.MarkupBuilder”类会有books这个方法?慢慢了解其中的机制后,觉得builder真是groovy精华的集大成者,所谓“解脱之味不独饮”,在此与朋友分享。
1. groovy中是如何调用方法的?
groovy基本上是兼容java语法的,但是为了更加方便开发人员,groovy作了许多便利的改进,比如说方法调用中省略括号
所以在java中常用的打印语句
同时调用方法的时候,传递参数可以加上参数的名字,例如
而groovy方法调用中与我以前所接触语言的最大不同就是Closure作为参数,而为了方便编写代码,一般也是将Closure写在方法调用的最后,因此上述代码的:
这样一来上述代码的字面意思就明白了,是方法调用中包含Closure,Closure中又包含方法调用的混合体,不过用了groovy的特殊写法。
(注:关于groovy中方法调用的更详细说明,请参考Groovy Statmements)
2. 无中生有的方法
知道上述语句的字面意思后,但还是不知道为什么这些方法调用会成功呢,因为我们的代码并没有定义这些方法。
在groovy中,所有的东西都是对象,而所有的对象都必须实现GroovyObject接口,该接口定义的方法不多,其中一个是:
Object invokeMethod(String name, Object args)。
原来在groovy中,编译器会将所有的方法调用转换成对invokeMethod的调用,例如:
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类型,我第一个想法就是是否能够用字符串来做方法名呢,例如:
实验结果证实这样的写法是OK的,而因为groovy中字符串的特性,上述代码还可以这么写:
我最近在编写一个数独解题程序,就大大享受到字符变量做方法名的好处。因为在解题中往往要对“行/列”两种情况都做一次,代码结构基本一致,只是多处调用的方法名和属性名不同。在普通Java程序中,要将这样的两段代码合并成一个方法少不了一大堆的if..then语句,而groovy只需要在开头设置好方法名即可,极为方便。
4. 创建自己的builder
如果你喜欢groovy builder这种模式,也可以创建自己builder,只要你的程序中存在用Builder模式可以解决的问题,groovy必然能帮上大忙,而且十分简便、优雅。
创建自己的builder也很简单,只需要继承BuilderSupport类,并实现其中几个抽象方法包括:
1)四种形式的createNode方法,groovy会根据你使用的形式自动调用相应的方法
2) void setParent(Object parent, Object child)
设置树状继承层次,当你创建子元素的时候,该方法就会被调用
3)void nodeCompleted(Object parent, Object node)
在子元素定义完毕后,该方法也会被自动调用。
例如上述生成xml的代码会被转换成以下的调用方式:
在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中的方法调用
为什么会触发调用xml.createNode()方法?说明这个问题的主要关键有两个:
1)Closure中变量、方法的作用范围,我们在Closure中能够访问到谁的变量、方法,为什么?
2)Closure是如何将对自身方法的访问“委派”给其他对象的?
如果我够勤奋的话,我会在另一篇blog讨论这两个问题 :)
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||
发表时间:2007-08-10
写的不错啊,看得出,对Groovy研究挺深啊,恭喜啊!
|
||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||
发表时间:2007-08-10
还有,可否将这样的Groovy的主题文章,也发布到Grails/Groovy的圈子里,也让广大Groovy fans来一起受益。
|
||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||
发表时间:2007-10-18
这些东西可能对没有接触过动态语言的java程序员们觉的新鲜,可Cloure、block等等所谓groovy的特性都是N多动态语言一直在用的东西。
|
||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||