Lombok Builder sa zadanom vrijednošću
1. Uvod
U ovom brzom vodiču istražit ćemo kako možemo pružiti zadane vrijednosti za atribute kada koristimo obrazac graditelja s Lombok.
Svakako pogledajte i naš uvod u Lombok.
2. Ovisnosti
U ovom ćemo uputstvu koristiti Lombok, a za to nam treba samo jedna ovisnost:
org.projectlombok lombok 1.18.10 pod uvjetom
3. POJO s graditeljem Lombok
Prvo, pogledajmo kako nam Lombok može pomoći da se riješimo uzorka koda potrebnog za implementaciju graditeljskog uzorka.
Započet ćemo s jednostavnim POJO:
javna klasa Pojo {privatni naziv niza; privatni logički izvornik; }
Da bi ova klasa bila korisna, trebat će nam getteri. Također, na primjer, ako želimo koristiti ovu klasu s ORM-om, vjerojatno će nam trebati zadani konstruktor.
Povrh svega, želimo graditelj za ovu klasu. S Lombokom sve to možemo dobiti s nekoliko jednostavnih napomena:
@Getter @Builder @NoArgsConstructor @AllArgsConstructor javna klasa Pojo {naziv privatnog niza; privatni logički izvornik; }
4. Utvrđivanje očekivanja
Definirajmo neka očekivanja za ono što želimo postići u obliku jediničnih testova.
Prvi i osnovni zahtjev je prisutnost zadanih vrijednosti nakon što gradimo objekt graditeljem:
@Test javna praznina givenBuilderWithDefaultValue_ThanDefaultValueIsPresent () {Pojo build = Pojo.builder () .build (); Assert.assertEquals ("foo", build.getName ()); Assert.assertTrue (build.isOriginal ()); }
Naravno, ovaj test ne uspijeva od @Graditelj napomena ne popunjava vrijednosti. Uskoro ćemo to popraviti.
Ako koristimo ORM, obično se oslanja na zadani konstruktor. Dakle, trebali bismo očekivati isto ponašanje od zadanog konstruktora kao i od graditelja:
@Test javna praznina givenBuilderWithDefaultValue_NoArgsWorksAlso () {Pojo build = Pojo.builder () .build (); Pojo pojo = novi Pojo (); Assert.assertEquals (build.getName (), pojo.getName ()); Assert.assertTrue (build.isOriginal () == pojo.isOriginal ()); }
U ovoj fazi ovaj test prolazi.
Sad da vidimo kako možemo oba testa proći!
5. Lombokova Graditelj.Zadano Bilješka
Od Lomboka v1.16.16, možemo koristiti @GraditeljUnutarnja napomena:
// napomene klase kao i prije javne klase Pojo {@ Builder.Default private String name = "foo"; @ Builder.Default privatni logički izvornik = true; }
Jednostavno je i čitljivo, ali ima nekih nedostataka.
Uz to će zadane vrijednosti biti prisutne kod graditelja, što će proći prvi testni slučaj. Nažalost, konstruktor no-args neće dobiti zadane vrijednosti, zbog čega drugi testni slučaj neće uspjeti. Čak i ako konstruktor no-args nije generiran, već je izričito napisan.
Ovaj nuspojava Graditelj.Zadano napomena je prisutna od početka i vjerojatno će biti s nama još dugo.
6. Inicijalizirajte Builder
Možemo pokušati učiniti da oba testa prođu definiranjem zadanih vrijednosti u minimalističkoj implementaciji graditelja:
// napomene klase kao i prije javna klasa Pojo {private String name = "foo"; privatni logički izvornik = true; javna statička klasa PojoBuilder {private String name = "foo"; privatni logički izvornik = true; }}
Na ovaj način će oba testa proći.
Nažalost, cijena je dupliciranje koda. Za POJO s desecima polja, održavanju dvostruke inicijalizacije moglo bi doći do pogreške.
Ali, ako smo spremni platiti ovu cijenu, trebali bismo se pobrinuti i za još jednu stvar. Ako preimenujemo klasu pomoću refaktoriranja unutar našeg IDE-a, statička unutarnja klasa neće se automatski preimenovati. Tada ga Lombok neće pronaći i naš će se kôd pokvariti.
Da bismo uklonili taj rizik, možemo ukrasiti napomenu graditelja:
// napomene klase kao prije @Builder (builderClassName = "PojoBuilder") javna klasa Pojo {private String name = "foo"; privatni logički izvornik = true; javna statička klasa PojoBuilder {private String name = "foo"; privatni logički izvornik = true; }}
7. Korištenje toBuilder
@Graditelj također podržava generiranje instance graditelja iz instance izvorne klase. Ova značajka nije omogućena prema zadanim postavkama. To možemo omogućiti postavljanjem toBuilder parametar u bilješci graditelja:
// napomene klase kao prije @Builder (toBuilder = true) javna klasa Pojo {private String name = "foo"; privatni logički izvornik = true; }
S ovim, možemo se riješiti dvostruke inicijalizacije.
Naravno, za to postoji cijena. Moramo stvoriti instancu klase da bismo stvorili graditelj. Dakle, također moramo modificirati svoje testove:
@Test javna praznina givenBuilderWithDefaultValue_ThenDefaultValueIsPresent () {Pojo build = new Pojo (). ToBuilder () .build (); Assert.assertEquals ("foo", build.getName ()); Assert.assertTrue (build.isOriginal ()); } @Test javna praznina givenBuilderWithDefaultValue_thenNoArgsWorksAlso () {Pojo build = new Pojo (). ToBuilder () .build (); Pojo pojo = novi Pojo (); Assert.assertEquals (build.getName (), pojo.getName ()); Assert.assertTrue (build.isOriginal () == pojo.isOriginal ()); }
Opet, oba testa prolaze, tako da imamo istu zadanu vrijednost koristeći konstruktor no-args kao i kada koristimo graditelj.
8. Zaključak
Dakle, pregledali smo nekoliko mogućnosti za pružanje zadanih vrijednosti za graditelj Lombok.
Nuspojava Graditelj.Zadano napomenu vrijedi paziti. Ali, i druge opcije imaju svoje nedostatke. Stoga moramo pažljivo birati na temelju trenutne situacije.
Kao i uvijek, kôd je dostupan na GitHub-u.