Java返回一个实现的构建器

ccgok5k5  于 2023-10-14  发布在  Java
关注(0)|答案(1)|浏览(108)

我为一个类做了一个函数构建器,它的工作原理如下:

new ComponentStatus.Builder()
        .with($ -> {
          $.name = element.getName();
          $.state = element.getState();
          $.status = element.getStatus();
          $.description = element.getStatusDescription();
        }).build();

此类是

public class ComponentStatus {

  private final String name;
  private final int state;
  private final int status;
  private final String description;

  ComponentStatus(String name, int state, int status, String description) {
    this.name = name;
    this.state = state;
    this.status = status;
    this.description = description;
  }

  public static class Builder {

    public String name;
    public int state;
    public int status;
    public String description;

    Builder with(
        Consumer<Builder> builderFunction) {
      builderFunction.accept(this);
      return this;
    }

    ComponentStatus build() {
      return new ComponentStatus(name, state, status, description);
    }

  }
}

现在我想给其他类添加一个构建器。with()方法将始终相同,因此我尝试在样板文件中创建一个保存接口

public interface Buildable {

  default Buildable with(
      Consumer<Buildable> builderFunction) {
    builderFunction.accept(this);
    return this;
  }

    Object build();
}

这不起作用,因为with()返回Buildable而不是<? extends Buildable>,但更改返回类型也不起作用。该怎么办呢?

xzv2uavs

xzv2uavs1#

要解决这个问题,可以使用带有自引用类型参数的泛型。
以下是如何定义Buildable接口:

import java.util.function.Consumer;

public interface Buildable<T extends Buildable<T>> {

    default T with(Consumer<T> builderFunction) {
        builderFunction.accept((T) this);
        return (T) this;
    }

    Object build();
}

现在更新ComponentStatus.Builder类来实现Buildable

public static class Builder implements Buildable<Builder> {

    public String name;
    public int state;
    public int status;
    public String description;

    @Override
    public ComponentStatus build() {
        return new ComponentStatus(name, state, status, description);
    }
}

这样,with方法将返回正确的构建器类型,允许方法链接,但是它将给予编译器关于“未检查的强制转换”的警告,因为不能保证它真正匹配T。
为了避免这种情况,您可以使用抽象类而不是接口。具体操作如下:

public abstract class AbstractBuilder<T extends AbstractBuilder<T>> {
  
  protected abstract T self();
  
  public T with(Consumer<T> builderFunction) {
    builderFunction.accept(self());
    return self();
  }
  
  public abstract Object build();
}

在每个具体构建器中,重写self()以返回this,正确键入:

public static class Builder extends AbstractBuilder<Builder> {
  
  public String name;
  public int state;
  public int status;
  public String description;
  
  @Override
  protected Builder self() {
    return this;
  }

  @Override
  public ComponentStatus build() {
    return new ComponentStatus(name, state, status, description);
  }
}

这种方法避免了未经检查的强制转换并维护了类型安全。

相关问题