Fluent Object Creation
Many posts have been written on this subject (overwhelmingly many) but I just wanted to contribute my two-cents and write a short post about how I use the Fluent Object Creation pattern or object builders in Java to instantiate Value Objects.
Value Objects are abstractions that are defined by their state (value) rather than their address in memory. Examples of value objects are things like money, a number, a coordinate, etc. They are used not to describe Business Objects but rather descriptions of concrete indivisible entities. Also, they make great candidates for adding them to collections and maps.
In Java, Value Objects should be declared final and provide no setter methods, basically making it’s state immutable after creation, this is a very important
requirement. Declaring them final makes them unable to serve as parent objects. This is done by design since value objects should model small and concrete entities. The reason being is that we should be able to create and compare multiple copies of these objects, which is always done by state not by reference. In addition, you should declare proper equals() and hashCode() methods to qualify for a proper value object. In C++, the same principles apply. In C++ you should make use of the Copy Constructor and overload the assignment and comparison operators. The Fluent Object Creation pattern makes value object instantiation elegant and clean. There are many benefits that can be gained by using fluent object creation as we will see shortly.
The end result of applying this pattern from the API user’s perspective will look like the following:
Money fiveEuros = new Money.Builder() .currency(Currency.EURO) .value(5.0L) .countryOfOrigin("Spain") .type("Coin") .reverse("Map of Europe") .obverse("Map of Spain") .addColor("Bronze") .addColor("Silver") .year("1880") .build();
I think you would agree that this pattern flows a lot more smoother as opposed to this:
Money fiveEuros = new Money(); fiveEuros.setCurrency(Currency.EURO); fiveEuros.setValue(5.0L); fiveEuros.countryOfOrigin("Spain"); fiveEuros.type("Coin"); fiveEuros.reverse("Map of Europe"); fiveEuros.obverse("Map of Spain"); List<String> colors = new ArrayList<String>(); for(String color: new String[] {"Bronze", "Silver"}) { colors.add(color); } fiveEuros.setColors(colors); fiveEuros.setYear("1880");
Which seems broken and has lots of typing and repetition. This is an example of building a pretty big value object in my opinion, most of tend to be very small. Before we talk about the benefits of creating objects this way, let’s have a look at the structure of this pattern:
public final class Money { private Long value; private String countryOfOrigin; private Currency currency; private String type; private String reverse; private String obverse; private List<String> colors; private Date year; private Money() { } // -- getters, hashCode, equals -- // // Static inner Builder class public static class Builder { private Money _temp = new Money(); public Builder value(Long val) { _temp.value = val; return this; } public Builder countryOfOrigin(String countryOfOrigin) { _temp.contryOfOrigin = countryOfOrigin; return this; } public Builder currency(Currency c) { _temp.currency = c; return this; } public Builder type(String t) { _temp.type = t; return this; } public Builder reverse(String r) { _temp.reverse = r; return this; } public Builder obverse(String o) { _temp.obverse = o; return this; } public Builder addColor(String c) { if(_temp.colors == null) { _temp.colors = new ArrayList<String>(); } _temp.colors.add(c); return this; } public Builder year(String y) { if(y == null || y.isEmpty()) { _temp.year = new Date(); } else { _temp.year = DateFormat.parse(y); } return this; } public Money build() { // Validate object if(Strings.isNullOrEmpty(_temp.name) || _temp.currency == null) { throw new IllegalArgumentException("Coin currency and value required"); } return _temp; } } }
This is also a matter of taste, but I prefer the static inner class approach. I like the canonical nature of referring to the builder as
Money.Builder. Also making it static is required since the builder instance needs to live independently of the enclosing class. I like this pattern because it has the following benefits:
- Greater object encapsulation: I can easily enforce object construction using builders by making the Money constructor private (this is just stylistic). This completely hides all of the intricacies of creating this object: list creation, date parsing, etc. From the user’s perspective, what we end up with is an object that is simple to instantiate. My illustration is a very simple one, but imagine more complex object graphs.
- Code readability: Using this pattern to create objects, makes unit tests and code very easy to read and follow.
- Less typing in the long run: Even though you have to add an extra builder method for every added attributes, the amount of typing you save in the long run makes it worth while.
Conclusion
Using the fluent creation pattern is more work up front, but the benefits of having it pays off at the end. It makes instantiating objects very elegant and clean. You don’t have to use it with Value Objects, most of the benefit of using Fluent Object Creation is when you need to build pretty complex object graphs, but I wanted to show that it can also suit small value objects.
Reference: Fluent Object Creation from our JCG partner Luis Atencio at the Reflective Thought blog.
Nice article, I like the builder pattern, but I think it lacks of some creational logic, for example, a client can do Money.Builder().build(); which will return an inconsistent Object. I guess the step builder pattern (http://rdafbn.blogspot.it/2012/07/step-builder-pattern_28.html) gives a better control of the object creation, and as you said “is more work up front, but the benefits of having it pays off at the end”.
Maybe because I never used it, but I’m not a huge fan of the Builder Pattern. I also wouldn’t use all those setters in the first, if you need N things to describe an object, why not pass them in the Constructor Money fiveEuros = new Money(Currency.Euro,5.0L, “Spain”,”Coin”, “Map of Europe”,”Map of Spain”,new String[]{“Bronze”,”Silver”}, 1180); I don’t think anything is wrong with the Builder per se, but I like to be able to look at the constructor and quickly see all the parameters needed, as well as their types. Good article though, I like seeing the innards of one of… Read more »
In your constructor, you pass 8 arguments, that’s a lot.
Moreover, it is easy to get the “reverse” and “obverse” accidentally swapped, that’s because most of the arguments are String, which increase the confusion between them.
These problems get solved – although not completely, you can still be distracted and do some errors – by the builder pattern.
Applying KISS principle I would write smart setters which return this and then chain setters. It has following advantages :
– make code simpler
– avoid duplication
– simplify adding fields to Money
Money fiveEuros = new Money()
.setCurrency(Currency.EURO)
.setValue(5.0L)
.setCountryOfOrigin(“Spain”)
.setType(“Coin”)
.setReverse(“Map of Europe”)
.setObverse(“Map of Spain”)
.setColors(“Bronze”, “Silver”) // overloaded setter with varargs
.setYear(“1880”);