I have existing model classes that always use builder pattern like this:
public class Model {
public static class Builder {
private boolean isValid;
private List<String> errorMessagesOrNull;
public Builder setIsValid(final boolean isValid) {
this.isValid = isValid;
return this;
}
public Builder setErrorMessages(final List<String> errorMessages) {
this.errorMessagesOrNull = errorMessages;
return this;
}
public List<String> getErrorMessages() {
return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull;
}
public Model Build() {
return new Model(this);
}
}
private boolean isValid;
private List<String> errorMessages;
private Model(final Builder builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
public boolean getIsValid() {
return isValid;
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
As you see, the model classes always have isValid
and errorMessages
. I want to write an abstract class to minimize the repeated logic for those model classes.
So I came up like this abstract class:
public abstract class AbstractModel<T extends AbstractModel<T>> {
public static abstract class Builder<T> {
private boolean isValid;
private List<String> errorMessagesOrNull;
public Builder<T> setIsValid(final boolean isValid) {
this.isValid = isValid;
return this;
}
public Builder<T> setErrorMessages(final List<String> errorMessages) {
this.errorMessagesOrNull = errorMessages;
return this;
}
public List<String> getErrorMessages() {
return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull;
}
public abstract T Build();
}
private boolean isValid;
private List<String> errorMessages;
private AbstractModel(final Builder<T> builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
public boolean getIsValid() {
return isValid;
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
But it's not really working as I intended. When I extends the abstract class:
public class Model extends AbstractModel<Model> {
// Empty here since all fields are extended
}
I cannot do something like:
Model model = new Model.Builder.setIsValid(true).Build();
I want the abstract class has Builder
static class, so that I don't need to write the static class Builder
every time.
Please advise.
You also need to implement the Builder
.
public class Model extends AbstractModel<Model>{
private Model(final Builder builder) {
super(builder);
}
public static class Builder2 extends AbstractModel.Builder<Model> {
@Override
public Model Build() {
return new Model(this);
}
}
}
then it possible to call
Model model = new Model.Builder2().Build();
EDIT
Also, the constructor of AbstractBuilder also must be protected
.
protected AbstractModel(final Builder<? extends Builder<T>> builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
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