这种带闭包的模式有名称吗?

Posted

技术标签:

【中文标题】这种带闭包的模式有名称吗?【英文标题】:Is there a name for this pattern with closures? 【发布时间】:2012-04-19 10:35:39 【问题描述】:

我经常看到在我们需要在访问对象之前执行查找代码的情况下使用一种模式。使用此模式时,通常以单词with 开头。

例如,我们需要先从数据库中检索客户记录,然后才能使用它们:

def withCustomer (id, closure) 
    def customer = getCustomer(id)
    closure(customer)


withCustomer(12345)  customer ->
    println "Found customer $customer.name"

Groovy 在闭包和匿名函数之间没有这样的区别。也许,我可以问一下这种模式是否有匿名函数的名称。

【问题讨论】:

【参考方案1】:

这是策略模式。闭包包含一些要作为参数传递给函数的行为,以便函数可以接受不同的行为。请参阅 Peter Norvig 的演示文稿Design Patterns in Dynamic Languages:

策略是一个变量,其值是一个函数(例如, 一流的功能,模式是不可见的)

【讨论】:

你怎么看@mgryszko answer @Arturo:我曾认为模板方法必然涉及继承,其中策略是它的替代品,而不是它的一种形式。 tech.puredanger.com/2007/07/03/pattern-hate-template 你觉得my own answer怎么样? @Arturo:刚才看到了。我不知道,投了赞成票。【参考方案2】:

在 Groovy 的 Closures - Formal Definition 中,它被称为“Passing Closures to Methods”。

Groovy 有一个特殊情况,将闭包定义为方法参数,以使闭包语法更易于阅读。具体来说,如果方法的最后一个参数是闭包类型,您可以使用括号外的显式闭包块调用该方法。例如,如果一个类有一个方法:

class SomeCollection 
    public void each ( Closure c )

然后你可以在括号外使用闭包定义来调用each():

SomeCollection stuff = new SomeCollection();
stuff.each()  println it 

也可以使用更传统的语法,还要注意在 Groovy 中很多情况下可以省略括号,所以这两种变体也是合法的:

SomeCollection stuff = new SomeCollection();

stuff.each  println it        // Look ma, no parens
stuff.each (  println it  )   // Strictly traditional

即使方法有其他参数,同样的规则也适用。唯一的限制是闭包参数必须是最后一个:

class SomeCollection 
  public void inject ( x, Closure c )


stuff.inject( 0 )  count, item -> count + item       // Groovy
stuff.inject( 0,  count, item -> count + item   )    // Traditional

这可能与“Groovy 问题”无关,但例如在 Scala 中,这种“形式”是函数柯里化的特例:

scala> def fun[A, B](a: A)(b: B) = true
fun: [A, B](a: A)(b: B)Boolean

scala> fun(1)2
res59: Boolean = true

【讨论】:

感谢您的回答,但您没有问我的问题。我问的是这个模式的名称,而不是闭包的使用。 这不是一种模式,而是一种语法形式,在 Groovy 中这种语法形式的名称是“Passing Closures to Methods”。如果你想更接近“模式”这个词,Scala 中的一个例子是“function currying”(虽然你可以用 Scala 的函数 currying 做的比这种语法形式多得多,但它恰好是特例之一)。【参考方案3】:

这取决于上下文。它可以是一种策略模式(参见 Nathan Hughes 的回答)。可以是模板方法模式。

Arturo 的示例似乎是一个模板方法。您定义通用算法步骤(在这种情况下获取客户)和自定义(作为闭包传递)。

【讨论】:

你觉得my own answer怎么样?【参考方案4】:

最后,我认为这种模式叫做Loan Pattern

贷款模式,确保一旦超出范围,资源就会被确定性地处置。

您可以在此处查看有关此模式的一些信息:

'Loan' pattern - 斯卡拉 Loan my Resource Pattern - Groovy

【讨论】:

以上是关于这种带闭包的模式有名称吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 IntelliJ IDEA 中调试 Java 期间生成的变量名称中的美元符号是啥意思?是闭包吗?

与在基于堆栈的系统上优化闭包有关的问题的名称是啥?

这种优化有名称吗?

这种语法 getSomeValues()[0] 有名称吗?

这种类型的缓存方案有名称吗?

这种不良做法/反模式的名称是啥?