Joshua Bloch的Builder模式和PMD警告

时间:2011-05-30 09:22:35

标签: 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;
  }
}

但是PMD报告了2个警告:

  1. (指向方法Builder.build()) 避免通过外部的私有构造函数进行实例化 构造函数的类。 通过私人方式实例化 来自外部的建设者 构造函数的类经常导致 生成访问者。一个工厂 方法,或非专有化 构造函数可以消除这一点 情况。生成的类文件 实际上是一个界面。它给 访问类的能力 调用新的隐藏包范围 接受接口的构造函数 作为补充参数。这个 变成私有构造函数 有效地融入一个包 范围,并且具有挑战性 辨别。
  2. 类无法实例化 不提供任何静态方法 或领域。一个私人的类 建设者,没有任何 静态方法或字段不能 使用。
  3. 我应该忽略这些警告吗?

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

2 个答案:

答案 0 :(得分:2)

关于如何删除重复。

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

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() {
}
}

答案 1 :(得分:1)

  

Pizza和。类中的私人字段   生成器是重复的。这将会   当私人数量烦人时   领域越来越大。有没有   避免它的方法?

我个人通过使用包含所有字段的第三个私有静态值对象类来解决这个问题,并在构建器和主类中使用它(字段访问由委托处理)。当然,这可能最终会增加行数/类数,但是如果你的构建器最终变得复杂,需要大量的字段和检查,那么这是非常宝贵的。

另外,在Pizza类上实际提供一个静态方法并没有什么坏处,该类使用必填字段构建Pizza对象。除非您当然不确定强制字段是什么,或者害怕强制字段在课程演变过程中可能会发生变化。重点是,只要你经过深思熟虑就可以证明你的行为是合理的(就像约书亚布洛赫所说的那样),你可以放心地忽略那些知道你知道自己在做什么的警告。 : - )

一次性片段:

public class Pizza {

    private final PizzaVO vo;

    private static class PizzaVO {

        int size;

        boolean cheese;

        boolean pepperoni;

        boolean bacon;
    }

    public static class Builder {

        private final PizzaVO vo = new PizzaVO();

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

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

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

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

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

    private Pizza(PizzaVO vo) {
        this.vo = vo;
    }

    public int getSize() {
        return vo.size;
    }

    // other getter setter methods as per your taste

}