I hope I picked the right group for this question…
I have this little framework I want to implement and I would like to have an opinion on it. In particular I am more concerned about the succinctness and style of the solution.
My class sketch looks like this:
public interface Builder<T> {
T build();
}
public interface RootObject {
public static abstract class MutableBuilder<T> implements Builder<T> {
protected MutableBuilder() { }
protected abstract void setA(A a);
protected abstract void setB(B b);
protected abstract void setC(C c);
protected abstract void setD(D d);
}
}
The goal is to have a Builder which returns an instance of (hopefully) immutable objects. The whole implementation is left to the client code, but I still want to give the imprinting of the Effective Java’s fluent interface.
If it was just for this, I would not be that puzzled. The problem comes into lay when I add the requirements:
- the framework needs to reflectively search through a generic
RootObject
implementation in order to find if theMutableBuilder
static inner class has been implemented. - if found, the framework instantiates one or more
MutableBuilder
dynamically (that is the reason why I have an abstract class with a constructor and return it or them to the client code.
The mere talking about reflection makes me wonder if I am doing the right thing. It looks a reasonable solution to me (of course).
4
If possible, go natural
I want to start by saying Java has built-in (“natural”) object creation techniques. Forcing your clients to declare types specifically for object creation for no specific reason will result in your framework being far from “easy-to-use”.
Avoid introspection if possible.
You’re misusing the (accepted) term “builder”.
A builder should only be used if a type has optional parameters. Not all types have this, so requiring a builder for every object is abuse of the pattern.
If you’re using the builder to decouple an implementation, the correct pattern to implement would be the factory method pattern
Prefer a factory over your current solution
In the comments of your post, you mentioned your framework now requires the client to pass in a builder. Although it’s nice you found a solution, there seems to be a bigger problem with your current design.
Builders should not define required properties, since the client isn’t forced to execute the behaviors provided by it. This turns the requirement into a (critically) recommended option, and is why builders still utilize class constructors. Your design currently misuses the pattern, and by the sound of the behavior you’re attempting to achieve, a factory would be better suited.