Recently I searched for a way to initialize a complex object without passing a lot of parameter to the constructor. I tried it with the builder pattern, but I don't like the fact, that I'm not able to check at compile time if I really set all needed values.
When I use the builder pattern to create my Complex
object, the creation is more "typesafe", because it's easier to see what an argument is used for:
new ComplexBuilder() .setFirst( "first" ) .setSecond( "second" ) .setThird( "third" ) ... .build();
But now I have the problem, that I can easily miss an important parameter. I can check for it inside the build()
method, but that is only at runtime. At compile time there is nothing that warns me, if I missed something.
Now my idea was to create a builder, that "reminds" me if I missed a needed parameter. My first try looks like this:
public class Complex { private String m_first; private String m_second; private String m_third; private Complex() {} public static class ComplexBuilder { private Complex m_complex; public ComplexBuilder() { m_complex = new Complex(); } public Builder2 setFirst( String first ) { m_complex.m_first = first; return new Builder2(); } public class Builder2 { private Builder2() {} Builder3 setSecond( String second ) { m_complex.m_second = second; return new Builder3(); } } public class Builder3 { private Builder3() {} Builder4 setThird( String third ) { m_complex.m_third = third; return new Builder4(); } } public class Builder4 { private Builder4() {} Complex build() { return m_complex; } } } }
As you can see, each setter of the builder class returns a different internal builder class. Each internal builder class provides exactly one setter method and the last one provides only a build() method.
Now the construction of an object again looks like this:
new ComplexBuilder() .setFirst( "first" ) .setSecond( "second" ) .setThird( "third" ) .build();
...but there is no way to forget a needed parameter. The compiler wouldn't accept it.
If I had optional parameters, I would use the last internal builder class Builder4
to set them like a "traditional" builder does, returning itself.
The Builder design pattern solves problems like: How can a class (the same construction process) create different representations of a complex object? How can a class that includes creating a complex object be simplified?
This pattern should be used: When it's necessary to use a constructor with a long parameter list or when there's a long list of constructors with different parameters. When it's necessary to build different representations of the same object.
The traditional builder pattern already handles this: simply take the mandatory parameters in the constructor. Of course, nothing prevents a caller from passing null, but neither does your method.
The big problem I see with your method is that you either have a combinatorical explosion of classes with the number of mandatory parameters, or force the user to set the parameters in one particular sqeuence, which is annoying.
Also, it is a lot of additional work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With