返回介绍

1 命令链

发布于 2025-01-04 00:44:53 字数 2408 浏览 0 评论 0 收藏 0

Groovy 可以使你省略顶级语句方法调用中参数外面的括号。“命令链”功能则将这种特性继续扩展,它可以将不需要括号的方法调用串接成链,既不需要参数周围的括号,链接的调用之间也不需要点号。举例来说, a b c d 实际上就等同于 a(b).c(d) 。它适用于多个参数、闭包参数,甚至命名参数。而且,这样的命令链也可以出现在赋值的右方。让我们来看看应用这一新的语法格式的范例:

// 等同于:turn(left).then(right)
turn left then right

// 等同于:take(2.pills).of(chloroquinine).after(6.hours)
take 2.pills of chloroquinine after 6.hours

// 等同于:paint(wall).with(red, green).and(yellow)
paint wall with red, green and yellow

// 命名参数
// 等同于:check(that: margarita).tastes(good)
check that: margarita tastes good

// 闭包作为参数
// 等同于:given({}).when({}).then({})
given { } when { } then { }

不带参数的链中也可以使用方法,但在这种情况下需要用括号。

// 等同于:select(all).unique().from(names)
select all unique() from names

如果命令链包含奇数个元素,链会由方法和参数组成,最终由一个最终属性访问:

// 等同于:take(3).cookies
// 同样也等于:take(3).getCookies()
take 3 cookies

借助命令链方法有趣的一点是,我们能够利用 Groovy 编写出更多的 DSL。

上面的范例展示了使用基于 DSL 的命令链,但是不知道如何创建一个。你可以使用很多策略,但是为了展示如何创建 DSL,下面列举一些范例,首先使用 map 映射与闭包:

show = { println it }
square_root = { Math.sqrt(it) }

def please(action) {
  [the: { what ->
  [of: { n -> action(what(n)) }]
  }]
}

// 等同于:please(show).the(square_root).of(100)
please show the square_root of 100
// ==> 10.0

第二个范例要考虑如何编写 DSL 来简化一个现存的 API。或许你需要把这些代码展示给顾客、业务分析师或测试员,有可能这些人并不是技艺非常精湛的 Java 开发者。我们将使用 Splitter ,一个 Google 的 Guava libraries 项目,因为它已经是一个良好的 Fluent API 了。下面展示如何使用它。

@Grab('com.google.guava:guava:r09')
import com.google.common.base.*
def result = Splitter.on(',').trimResults(CharMatcher.is('_' as char)).split("_a ,_b_ ,c__").iterator().toList()

对于 Java 开发者而言,这段代码很容易明白,但如果面对的是目标顾客,或者要写很多这样的语句,那就可能显得有些啰嗦了。再次提醒一下,DSL 的编写手段多种多样。利用映射和闭包来将它简化一下,首先编写一个辅助函数:

@Grab('com.google.guava:guava:r09')
import com.google.common.base.*
def split(string) {
  [on: { sep ->
  [trimming: { trimChar ->
    Splitter.on(sep).trimResults(CharMatcher.is(trimChar as char)).split(string).iterator().toList()
  }]
  }]
}

然后找到原始范例中的这一行:

def result = Splitter.on(',').trimResults(CharMatcher.is('_' as char)).split("_a ,_b_ ,c__").iterator().toList()

替换成下面这行:

def result = split "_a ,_b_ ,c__" on ',' trimming '_\'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文