I started to write a ‘quick’ response to this post about builders and it kind of got out of hand, so I’m putting it up here instead.
The post isn’t bad, but I think that Marcin is getting the builder and factory patterns a little mixed up. To recap:
The intent of the Builder Pattern is to separate out the construction of an object from it’s final representation. Doing this makes it easier to enforce preconditions and invariants, and also makes the object construction easier to read in languages without keyword arguments.
The intent of the Factory Pattern on the other hand, is to delegate responsibility for creating an object to somebody else. It is commonly used in dependency injection frameworks.
A concrete example should serve to illustrate the differences.
A Builder Example
Assume that we have an interface for a simple Pojo:
1 2 3 4 5 6 7 |
|
and a default implementation (shown here as a separae class, but it could also be a static inner class in the interface):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Even with just a few fields like this invoking the constructor becomes somewhat ugly:
1 2 |
|
Without referring to the docs or source code how do you know what all of those strings mean? How do you know that you have them in the correct order? And if it seems reasonable clear in this example imaging if your Pojo was mainly non-string data!
1
|
|
Clear as mud, right?
Other languages don’t have this problem, for example in Objective-C we would write something like:
1 2 |
|
which is much clearer. Ruby, Python, and other languages all have similar constructs. Adding a builder allows us to gain the same level of clarity in Java, and it provides a good place for us to perform any additional checks before creating the object. Here’s a typical implementation and an example of calling it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
|
Again, all pretty clear now, and HotSpot will inline all of those method calls no there should be no additional overhead once the JVM is up and running.
A Factory Example
Factories are different, but it would be common for a factory to use a builder to create the objects that it vends. For example, here is a factory for employee objects (it doesn’t need to have the word Factory in it’s name):
1 2 3 4 |
|
We can then have different implementations of this, maybe one that loads data from a CSV or JSON file for testing purposes, and one that loads data via JDBC for production use.
Aside: if you’re familiar with domain-driven design you’ll be forgiven for noticing a lot of overlap between the factory pattern and DDD’s concept of repositories, they’re very similar concepts. One difference being that factories are often able to create new objects ex nihilo while repositories usually retreive objects from external sources. Compare the findById()
method with the newInstance()
methods employed by many of the factory classes in the JDK.
Hopefully you can see from this post that the two patterns have different—if complementary—aims.
A complete example project with all of this code, as well as test cases and a CSV based implementation the the factory are available on Github.