12 listopada 2011

Płynny interfejs java.nio.file.attribute.AclEntry.Builder w Java 7

Trudno stwierdzić, jak wiele jest tych ciekawostek w Java 7 pod kątem wzorców użytych do rozbudowy API, ale trafiłem dzisiaj na java.nio.file.attribute.AclEntry.Builder, który zbudowany jest w oparciu o warte wzmiankowania konstrukcje programistyczne - wzorzec Budowniczy z tzw. "fluent interface" (często tłumaczone dosłownie jako "płynny interfejs"), czyli techniką konstruowania klas tak, aby metoda zwracała instancję obiektu, dla której została wywołana. W ten sposób możemy wywoływać metody, jedna po drugiej, przez ich łączenie.

Jakkolwiek wątpię, abym często obcował z AclEntry i jej pobratyńcami, to cieszę się, że pojawiła się ta klasa, która uważam, że spopularyzuje ten sposób budowania API w Javie.

Skoro rysunek może zastąpić 1000 słów, to może przykładowy kod z AclEntry.Builder również?
package pl.japila.java7.nio2;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryFlag;
import java.nio.file.attribute.AclEntryPermission;
import java.nio.file.attribute.AclEntryType;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.attribute.UserPrincipalLookupService;

public class AclEntryDemo {

     public static void main(String[] args) throws IOException {
          // who...
          UserPrincipalLookupService principalLookupService =
              FileSystems.getDefault().getUserPrincipalLookupService();
          UserPrincipal principal = principalLookupService.lookupPrincipalByName("jacek");
          System.out.printf("Principal: %s %n", principal);
         
          // ...does what.
          AclEntry aclEntry = AclEntry.newBuilder()
                    .setType(AclEntryType.ALLOW)
                    .setPrincipal(principal)
                    .setPermissions(AclEntryPermission.LIST_DIRECTORY)
                    .setFlags(AclEntryFlag.DIRECTORY_INHERIT)
                    .build();
          System.out.printf("ACL Entry: %s %n", aclEntry);
     }

}
Niezłe, co? A to wszystko dostępne w Java 7.

Przy okazji, warto zajrzeć na blog pragmatists.pl, w którym Paweł Lipiński przedstawił temat we wpisie Płynne interfejsy.

Czy ma ktoś pomysły, gdzie użyć AclEntry i jej podobych? A może już jest w użyciu u Ciebie? Jakie zastosowanie? Zachęcam do podzielenia się doświadczeniami, których mi zauważalnie brakuje.

4 komentarze:

  1. Wszystkim eclipsowcom pragnącym zakosztować w 'płynnym' bodowaniu swoich obiektów polecam plugin Fluent Builder Generator.

    http://code.google.com/p/fluent-builders-generator-eclipse-plugin/

    OdpowiedzUsuń
  2. Jakoś nie podoba mi się tłumaczenie "płynny" i podana definicja. To bym nazwał raczej "chain invocation" niż "fluent interface". No i zwracanie ciągle tego samego obiektu nie zawsze jest dobrym pomysłem w przypadku drugiego, lepiej mieć różne "etapy" wtedy wywołania kolejnych metod ograniczają/zmieniają dostępne możliwości :)

    OdpowiedzUsuń
  3. Krzysiek, a gdzie jest różnica między nimi? Dla mnie jeden nie istnieje bez drugiego.

    OdpowiedzUsuń
  4. Wzorzec budowniczy nie koniecznie musi być fluent. Z kolei fluent interface może być zastosowany nie tylko w tym wzorcu.

    W podanym przykładzie z AclEntry to wygląda po prostu jak uproszczony zapis setterów, co bardziej pasuje pod "chain invocation", o którym wspomniał Krzysiek.

    Przykładowo zamiast ".setType(AclEntryType.ALLOW)" można by np. napisać ".withAllowType()". Nie znam tej klasy, więc nie wiem czy faktycznie by to miało sens - ale będzie to bardziej fluent niż kolejny setter.

    Oczywiście trzeba uważać z przykładami, które są w sieci. Sama zamiana "set" na "with" fluent interface'u jeszcze nie czyni :)

    OdpowiedzUsuń