5

Często widzę wzór używany w okolicznościach, w których mamy kod wyszukiwania, który musi zostać wykonany, zanim uzyskamy dostęp do obiektu. Podczas korzystania z tego wzoru zwykle zaczyna się od słowa with.Czy istnieje nazwa tego wzoru z zamknięciami?

Na przykład, mamy dane klientów, które muszą być pobierane z bazy danych, zanim można z nich korzystać:

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

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

Groovy nie ma takiego rozróżnienia pomiędzy zamknięciami lub funkcji anonimowych. Być może, mógłbym zapytać, czy istnieje nazwa tego wzoru z anonimowymi funkcjami.

Odpowiedz

4

To jest wzór strategii. Zamknięcie zawiera pewien element zachowania, który ma zostać przekazany do funkcji jako argument, tak aby funkcja mogła akceptować różne zachowania. Zobacz Peter Norvig na prezentacji Design Patterns in Dynamic Languages:

Strategia jest zmienną, której wartość jest funkcją (na przykład z funkcji pierwszej klasy, wzór jest niewidoczny)

+0

Co sądzisz o [@mgryszko answer] (http://stackoverflow.com/a/10093625/462015) –

+0

@ Arturo: myślałem o metodzie szablonów jako koniecznie obejmujących dziedziczenie, gdzie strategia była alternatywą dla niego, nie jego forma. http://tech.puredanger.com/2007/07/03/pattern-hate-template/ –

+0

Co sądzisz o [moja własna odpowiedź] (http://stackoverflow.com/a/10306434/462015)? –

2

W Groovy's Closures - Formal Definition jest on nazywany "Przekazywanie zamknięć do metod".

Groovy ma specjalny przypadek do definiowania zamknięć jako argumentów metod, aby składnia zamknięcia była łatwiejsza do odczytania. W szczególności, jeśli ostatnim argumentem metody jest typ Zamknięcie, możesz wywołać metodę z jawnym blokiem zamknięcia poza nawiasem. Na przykład, jeśli klasa ma metodę:

class SomeCollection { 
    public void each (Closure c) 
} 

Następnie można powołać each() z definicji zamknięcia poza nawias:

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

bardziej tradycyjnych składnia jest również dostępny, a także pamiętać, że w Groovy można abstrahować nawias w wielu sytuacjach, więc te dwie odmiany są również prawny:

SomeCollection stuff = new SomeCollection(); 

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

Ta sama zasada ma zastosowanie nawet jeśli metoda ma inne argumenty. Jedynym ograniczeniem jest to, że argument Zamknięcie musi być ostatnia:

class SomeCollection { 
    public void inject (x, Closure c) 
} 

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

które mogą nie być odpowiednie do „Groovy pytanie”, ale na przykład w Scala, to „forma” jest szczególnym przypadkiem funkcja curling:

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 
+0

Dzięki za odpowiedź, ale nie zapytać moje pytanie. Zapytałem o nazwę tego wzoru, a nie o użycie zamknięć. –

+0

to nie jest wzorzec, ale forma składni, a nazwa tej składni w Groovy to "** Przekazywanie zamknięć do metod **". Jeśli chcesz być bliżej słowa "wzór", przykładem w Scali jest "** funkcja currying **" (chociaż jest dużo więcej, co możesz zrobić z funkcją Scali currying niż ta forma składni, ale tak się składa być jednym ze szczególnych przypadków). – tolitius

1

To zależy od kontekstu. Może to być wzór strategii (patrz odpowiedź Nathana Hughesa). Może to być szablon Metoda szablonów.

Przykład Arturo wydaje się być metodą szablonu. Użytkownik definiuje wspólne kroki algorytmu (w tym przypadku uzyskanie klienta) i dostosowania (przekazywane jako zamknięcie).

+0

Co sądzisz o [moja własna odpowiedź] (http://stackoverflow.com/a/10306434/462015)? –

1

Wreszcie, myślę, że ten wzór nazywa się Wzór pożyczki.

Wzór pożyczki, zapewnia, że ​​zasób jest deterministycznie unieszkodliwiony, gdy wykracza poza zakres.

Można zobaczyć kilka informacji na temat tego wzoru tutaj:

Powiązane problemy