I had the pleasure to work with the author of this article on Java Currying.
The article introduces a fluent builder pattern via the use of a series of functional interfaces and a function to chain them together. It allows us to build something like looks like this:
ComplexObject object = withDate(LocalDateTime.now()) .withName("Bertie") .withQuantity(1) .withManufacturer("Apple") .build();
The above looks like a normal builder. Each phase of it is actually a functional interface. E.g.
withDatemight return a
WithDate type that has got the
withName function on it to move through the build operation. The last one
withManufacturer returns a type with just the
build function on it.
Can’t we just use Lombok?
No! Jeez no! No no no. See here on Lombok!
Why is this Builder Better?
Builders tend to suffer from a few annoying issues:
- They don’t enforce the provision of all values
- The builder class ends up as a duplicate of the POJO it builds
- People can call the methods in any order, leading to code that lacks convention
But a builder in general can help us:
- Discover the properties that need to be expressed – the builder has methods showing what needs building
- Avoid confusing values when some of the inputs are the same type – compare this with a constructor that takes a couple of easily switched over String objects
This particular build pattern:
- Enforces the order, making the build operation into a consistent DSL
- Enforces providing all values
Anything that turns your public APIs into a strongly typed DSL is generally a good thing, especially if you can build it in a relatively lightweight way.
Lombok does similar things, with less robustness, and less transparency. The above technique is working well for me at the moment.