I showed off a hand-rolled example Java builder pattern today. It has some benefits over existing builder solutions, but is more work than I like:
- All parts of the builder are immutable; you can pass a partially built object for another object to complete (I'm looking at you, Lombok)
- It's syntactically complete; that is, code won't compile without providing all arguments for the thing to build
- It's easy to generalize; in fact, I'm thinking about an annotation processor to generate it for you (but not there quite yet)
@EqualsAndHashCode @ToString public final class CartesianPoint { public final int x; public final int y; public static Builder builder() { return new Builder(); } private CartesianPoint(final int x, final int y) { this.x = x; this.y = y; } public static final class Builder { public WithX x(final int x) { return new WithX(x); } @RequiredArgsConstructor public static final class WithX { private final int x; public WithY y(final int y) { return new WithY(y); } @RequiredArgsConstructor public final class WithY { private final int y; public CartesianPoint build() { return new CartesianPoint(x, y); } } } } }
That was a lot to say! Which is why most times you don't hand-roll builders. Usage is obvious:
@Test public void shouldBuild() { final CartesianPoint point = CartesianPoint.builder(). x(1). y(2). build(); assertThat(point.x).isEqualTo(1) assertThat(point.y).isEqualTo(2); }
Adding caching for equivalent values is not hard:
public static final class Builder { private static final ConcurrentMapcache = new ConcurrentHashMap<>(); public WithX x(final int x) { return new WithX(x); } @RequiredArgsConstructor public static final class WithX { private final int x; public WithY y(final int y) { return new WithY(y); } @RequiredArgsConstructor public final class WithY { private final int y; public CartesianPoint build() { final CartesianPoint point = new CartesianPoint(x, y); final CartesianPoint cached = cache. putIfAbsent(point, point); return null == cached ? point : cached; } } } }
No comments:
Post a Comment