To date I use the following implementation of the builder pattern (as opposed to the implementation described here):
public class Widget {
public static
A builder/factory still lets you decouple interface from implementation type (or lets you plug in an adapter, etc), assuming Widget
becomes an interface and you have a way to inject or hide the new Widget.Builder
.
If you don't care about decoupling, and your implementation is a one-off, then you're right: the builder pattern isn't much more useful than a normal constructor (it still labels its arguments with the attribute-per-builder-method style.)
If you are repeatedly creating objects with little variation in the arguments, then it may still be helpful. You could pass in, cache, etc the intermediate builder acquired after plugging in several attributes:
Widget.Builder base = new Widget.Builder(name, price).model("foo").manufacturer("baz");
// ...
Widget w1 = base.serialNumber("bar").build();
Widget w2 = base.serialNumber("baz").build();
Widget w3 = base.serialNumber("quux").build();
This assumes that your builders are immutable: builder setters don't set an attribute and returning this
, but return a new copy of themselves with the change instead. As you pointed out above, parameter objects are another way to get around repeated argument boilerplate. There, you don't even need the builder pattern: just pass the parameter object to your implementation constructor.