5

オブジェクトにアクセスする前に実行する必要のあるルックアップコードがある状況で使用されるパターンをよく目にします。このパターンを使用する場合、通常は単語で始まりますwith

たとえば、使用する前にデータベースから取得する必要のある顧客レコードがあります。

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

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

Groovyは、クロージャーと無名関数をそのように区別しません。おそらく、無名関数を持つこのパターンの名前があるかどうかを尋ねることができます。

4

4 に答える 4

4

これが戦略パターンです。クロージャは、関数がさまざまな動作を受け入れることができるように、引数として関数に渡される動作の一部を保持します。PeterNorvigのプレゼンテーション「動的言語でのデザインパターン」を参照してください。

ストラテジーは、値が関数である変数です(たとえば、ファーストクラスの関数では、パターンは表示されません)

于 2012-04-05T17:47:19.957 に答える
2

Groovyのクロージャ-正式な定義では、単に「クロージャをメソッドに渡す」と呼ばれています。

Groovyには、クロージャ構文を読みやすくするために、メソッド引数としてクロージャを定義するための特別なケースがあります。具体的には、メソッドの最後の引数がClosure型の場合、括弧の外側に明示的なクロージャブロックを指定してメソッドを呼び出すことができます。たとえば、クラスにメソッドがある場合:

class SomeCollection {
    public void each ( Closure c )
}

次に、括弧の外にあるクロージャー定義を使用してeach()を呼び出すことができます。

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

より伝統的な構文も利用可能であり、Groovyでは多くの状況で括弧を削除できるため、これら2つのバリエーションも合法であることに注意してください。

SomeCollection stuff = new SomeCollection();

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

メソッドに他の引数がある場合でも、同じルールが適用されます。唯一の制限は、Closure引数が最後でなければならないということです。

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
于 2012-04-05T17:08:17.903 に答える
1

それは文脈に依存します。これは戦略パターンである可能性があります(Nathan Hughesの回答を参照)。テンプレートメソッドパターンにすることができます。

Arturoの例はテンプレートメソッドのようです。一般的なアルゴリズムステップ(この場合は顧客を取得する)とカスタマイズ(クロージャーとして渡される)を定義します。

于 2012-04-10T17:35:32.267 に答える
1

最後に、このパターンはローンパターンと呼ばれていると思います。

ローンパターンは、リソースがスコープ外になると、リソースが決定論的に破棄されることを保証します。

このパターンに関するいくつかの情報をここで見ることができます:

于 2012-04-24T21:43:07.417 に答える