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:
I think you would agree that this pattern flows a lot more smoother as opposed to this:
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:
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.
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.