Search code examples
javagenericsbuilder-pattern

Builder Pattern Java: How to reference generic type in BaseBuilder for Generic BaseClass


I want to implement Builder pattern for Generic Base class and Sub class stuck at defining Generic type in Base Builder. Here are the classes.

Sub Class:

public class Sub extends Base<T> {
 private final String key;
      private Sub(Builder builder) {
       super(builder);
       this.key = builder.key;
     }
public static SubBuilder extends Base.BaseBuilder<SubBuilder> {
     String key;
    public SubBuilder key(String key) {
      this.key = key;
      return this;
    }
  @Override
  public Sub build() {
  return new Sub(this);
  }
}
}

Base Class :


public class Base<T> {
 private final T type;
 protected Base(BaseBuilder<?> build) {
  this.type = build.type; 
}
//Base Builder
public static class BaseBuilder<B extends BaseBuilder<B>> {
 T type;  //This is obviously not right because T is not static reference 
 public B type(T type) {
 this.type = type;
  return (B)this;
}
public Base build() {
return new Base(this);
}
} 
}

As mentioned can't reference T type in BaseBuilder. How to set T using builder here. Can't remove static from BaseBuilder too. Is builder pattern suitable for this kind of problems?


Solution

  • Add T type parameter to BaseBuilder, Sub and SubBuilder:

    public class Base<T> {
        private final T type;
    
        protected Base(BaseBuilder<?, T> build) {
            this.type = build.type;
        }
    
        public static class BaseBuilder<B extends BaseBuilder<B, T>, T> {
            private T type;
    
            public B type(T type) {
                this.type = type;
                return (B) this;
            }
    
            public Base<T> build() {
                return new Base<>(this);
            }
        }
    }
    
    public class Sub<T> extends Base<T> {
        private final String key;
    
        private Sub(SubBuilder<T> builder) {
            super(builder);
            this.key = builder.key;
        }
    
        public static class SubBuilder<T> extends BaseBuilder<SubBuilder<T>, T> {
            private String key;
    
            public SubBuilder<T> key(String key) {
                this.key = key;
                return this;
            }
    
            @Override
            public Sub<T> build() {
                return new Sub<>(this);
            }
        }
    }