Nie nudząc technicznymi szczegółami przejdźmy do przykładu. Klasę np. Order oznaczamy adnotacją @GenerateBuilder, która informuje procesor, że dla niej ma zostać wygenerowany builder:
@GenerateBuilder public class Order { private List<OrderItem> items; private Date createDate; private boolean realized; public boolean isRealized() { return realized; } public void orderRealized() { // very complex implementation realized = true; } }Żeby w jakiś sposób automatycznie aktualizować istniejące buildery o nowe pola, które doszły w klasie Order (lub odpowiednio usuwać metody inicjujące nieistniejące pola), builder został rozbity na 2 klasy. Jedna z nich jest aktualizowana zawsze przy uruchomieniu procesora, druga generowana tylko raz, dzięki czemu możemy do niej dodawać własne metody budujące. Dla klasy Order powstaną następujące klasy:
public abstract class AbstractOrderBuilder<B> extends AbstractBuilder<Order, B> { public abstract B withItems(List<OrderItem> items); public abstract B withCreateDate(Date createDate); public abstract B withRealized(boolean realized); public B withItems(OrderItem... items){ return withItems(new ArrayList<OrderItem>(Arrays.asList(items))); } }
public abstract class OrderBuilder extends AbstractOrderBuilder<OrderBuilder> { public static OrderBuilder anOrder(){ return AbstractBuilderFactory.createImplementation(OrderBuilder.class); } }Samo użycie może wyglądać następująco:
@Test public void shouldCreateRealizedOrder() { // when Order order = anOrder().withRealized(true).build(); // then assertTrue(order.isRealized()); }Klasę OrderBuilder można rozszerzać, wywołując rzeczywiste metody domenowe, np:
public abstract class OrderBuilder extends AbstractOrderBuilder<OrderBuilder> { public static OrderBuilder create() { return AbstractBuilderFactory.createImplementation(OrderBuilder.class); } public OrderBuilder realized() { Order order = targetObject(); // invoking real domain method order.orderRealized(); // other methods return builder(); } }
@Test public void shouldCreateRealizedOrder() { // when Order order = anOrder().realized().build(); // then assertTrue(order.isRealized()); }Do podłączenia procesora do projektu może zostać wykorzystany ant, maven, eclipse. Jest również możliwość użycia generatora w starym stylu, czyli wygenerowania ciała klasy buildera do konsoli.
Procesor może również poszukiwać klas z adnotacjami JPA (@Entity, @Ebeddable, @MappedSuperclass).
Do poznania szczegółów odsyłam do wiki projektu. Zachęcam do forkowania i dzielenia się uwagami.