演化架构与紧急设计: 语言、表达性与设计:第 1 部分
2009-09-12 00:00:00 来源:WEB开发网清单 10 显示了一个示例应用程序,这是用 Groovy 编写的一个小菜谱 DSL:
清单 10. 用 Groovy 编写的菜谱 DSL
def recipe = new Recipe("Spicy Bread")
recipe.add 1.gram.of("Nutmeg")
recipe.add 2.lbs.of("Flour")
println recipe
清单 10 中比较有意思的代码行是中间几行,它定义了菜谱的原料。Groovy 使您能将新方法添加到任何类(包括 java.lang.Integer,这是 Groovy 对待数字字面值的方式)。这是我们能够调用数字值上方法的方式。要向现有类添加新方法,可以使用叫做 ExpandoMetaClass 的 Groovy 机制,如清单 11 所示:
清单 11. 通过 ExpandoMetaClass 向 Integer 添加方法
Integer.metaClass.getGram { ->
delegate
}
Integer.metaClass.getGrams {-> delegate.gram }
Integer.metaClass.getPound { ->
delegate * 453.29
}
Integer.metaClass.getPounds {-> delegate.pound }
Integer.metaClass.getLb {-> delegate.pound }
Integer.metaClass.getLbs {-> delegate.pound }
在 清单 11 中,我在 Integer 的元类上定义了一个新属性,叫做 getGram(它使我能从 Groovy 中调用它并且不用 get 前缀)。在属性定义中,delegate 指的是实例 Integer 的值;我使 DSL 中所有度量单位都是克,这样它会返回整数值。DSL 的目标之一是流畅性,因此我还定义了一个复数版本的 gram 属性,叫做 getGrams,使 DSL 代码更可读。我还需要支持磅作为度量单位,因此我还定义了一个 pound 属性家族。
更多精彩
赞助商链接