这些天我正在学习设计模式。有很多关于编程设计模式的文档,但我对闭包设计模式很感兴趣。
我找到了关于Design Patterns in Java and Groovy的Venkat Subramaniam的演示文稿,并根据我自己的经验提取了一些涉及闭包和其他模式的演示模式。
需要在操作之前和之后执行的一对操作。
def operations(closure) {
println "Open"
closure()
println "Close"
}
operations { println "Operation" }
===> Open
===> Operation
===> Close
在运行时指定对象的行为。
def selectValues(number, closure) {
def list = []
1.upto(number) {
if (closure(it)) list << it
}
return list
}
assert [2, 4, 6, 8, 10] == selectValues(10) { it % 2 == 0 } // even
assert [1, 3, 5, 7, 9] == selectValues(10) { it % 2 != 0 } // odd
允许顺序访问元素。
def listNumbers(closure) {
(0..5).each { closure it }
}
listNumbers {
if (it < 3) println "$it is a little number"
else println "$it is a big number"
}
===> 0 is a little number
===> 1 is a little number
===> 2 is a little number
===> 3 is a big number
===> 4 is a big number
===> 5 is a big number
创建并执行条件操作。
def greet(user, successClosure, failClosure) {
if (isAdmin(user)) successClosure()
else failClosure()
}
greet(user, { println "Hi Admin!" }, { println "Hello User" })
我想知道更多的闭包设计模式。有关于这个主题的参考吗?随意用您最喜欢的编程语言编写新模式。
我写了一篇关于这个主题的帖子(Groovy和Ruby但内容相同):
Closure Design Patterns
Closure Design Patterns. Ruby Edition
答案 0 :(得分:7)
我认为你对lambda /匿名函数的封闭感到困惑?
Closure是一个绑定变量的词汇上下文。简而言之,如果从函数内定义函数,则内部函数可以访问外部函数中定义的变量。在这种情况下,“词汇上下文”是外部函数。
Lambdas是没有变量赋值的函数。例如,在Ruby中,您可以将块传递给函数,并且函数可以仅使用yield
关键字在内部调用它。在JavaScript中,您可以定义一个函数并同时将其作为参数传递。你的例子都是这样的。
First-class functions是另一回事,它是可以像常规对象一样传递的函数。您可以将它们作为参数传递给函数调用并保持对它们的引用。这就像Ruby的Proc
。在JS中,所有函数都是一流的,所有函数都是对象。
在JavaScript中,我们可以用一个愚蠢的例子来说明所有3个:
function foo(func) {
func();
}
var bar = function() { // bar is a first-class function
var i = 5;
foo(function() { // this is the anonymous function (lambda)
console.log(i); // i is the closure-bound variable
});
}
foo(bar); // Prints 5
所以,这会让你的问题变得混乱。闭包是一种语言特征,而不是设计模式。有许多设计模式,其实现可以使用闭包或lambda或modulo或构造函数或其他,正如您已经展示了这些示例。虽然这些都不是classical design patterns,所以我不确定我是否会打电话给他们。也许我会称他们为糖。
Java可以实现各种设计模式,但没有这些功能。很多这样的东西都是通过接口完成的,这是一种完全不同的语言特性。
答案 1 :(得分:1)
正如人们所说的那样,这些并不是真正的“模式”,而且非常适合Groovy,但是闭包的另外两种用途是:
def sum = { Collection a -> a.sum() }
def first2 = { Collection a -> a.take( 2 ) }
def take2andAdd = sum << first2
println take2andAdd( [ 1, 2, 3, 4 ] ) // Prints 3
def add = { a, b -> a + b }
def add2 = add.curry( 2 )
println add2( 3 ) // Prints 5
当然,这些可以结合起来:
def square = { a -> a * a }
def add = { a, b -> a + b }
def add2 = add.curry( 2 )
def add2andSquare = square << add2
println add2andSquare( 3 ) // prints 25
答案 2 :(得分:1)
我同意其他的回答,因为谈论闭包设计模式并没有多大意义(特别是当你真的在谈论一流的功能时);)。我认为你真正想要的是如何在实现设计模式时使用诸如一流函数,lambdas和闭包之类的工具。虽然它特定于Groovy,但您可能会发现查看此页面很有用:http://groovy.codehaus.org/Design+Patterns+with+Groovy
例如,“Loan my Resource Pattern”显示了如何以与“Execute Around Method”模式非常相似的方式使用Closures,而“访问者模式”也是一个也充分利用了Closures并且不是' t列入您的清单。