Joshua Bloch的Builder模式和PMD警告

cha*_*nce 5 java pmd builder-pattern

我使用Joshua Bloch的Builder模式编写了一个类,类似于这个Pizza示例:

public class Pizza {
  private int size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder {
    //required
    private final int size;

    //optional
    private boolean cheese = false;
    private boolean pepperoni = false;
    private boolean bacon = false;

    public Builder(int size) {
      this.size = size;
    }

    public Builder cheese(boolean value) {
      cheese = value;
      return this;
    }

    public Builder pepperoni(boolean value) {
      pepperoni = value;
      return this;
    }

    public Builder bacon(boolean value) {
      bacon = value;
      return this;
    }

    public Pizza build() {
      return new Pizza(this);
    }
  }

  private Pizza(Builder builder) {
    size = builder.size;
    cheese = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon = builder.bacon;
  }
}
Run Code Online (Sandbox Code Playgroud)

但PMD报告了2个警告:

  1. (指向方法Builder.build())避免通过构造函数类外部的私有构造函数进行实例化.通过私有构造函数从构造函数类的外部实例化通常会导致生成访问器.工厂方法或构造函数的非私有化可以消除这种情况.生成的类文件实际上是一个接口.它使访问类能够调用一个新的隐藏包作用域构造函数,该构造函数将接口作为补充参数.这将私有构造函数有效地转换为具有包范围的私有构造函数,并且难以辨别.
  2. 类无法实例化,也不提供任何静态方法或字段.不能使用具有私有构造函数且没有任何静态方法或字段的类.

我应该忽略这些警告吗?

另一个问题是:在类的私有字段PizzaBuilder重复的.当私人领域的数量越来越大时,这将是烦人的.有什么办法可以避免吗?

wee*_*ens 2

关于如何删除重复项。

我会得到更多的反对票:)但也许是这样的?

class Pizza {
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;

public static class Builder {
    private Pizza pizza = new Pizza();

    public Builder(int size) {
        pizza.size = size;
    }

    public Builder cheese(boolean value) {
        pizza.cheese = value;
        return this;
    }

    public Builder pepperoni(boolean value) {
        pizza.pepperoni = value;
        return this;
    }

    public Builder bacon(boolean value) {
        pizza.bacon = value;
        return this;
    }

    public Pizza build() {
        return pizza;
    }
}

private Pizza() {
}
}
Run Code Online (Sandbox Code Playgroud)

  • 我不喜欢这个。您可以通过调用 build() 后创建披萨的构建器更改披萨上的字段。构建器模式的最佳用途之一是简化不可变类的创建。 (7认同)