5

Joshua BlochのBuilderパターンを使用してクラスを作成しました。これは、このピザの例に似ています。

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. クラスはインスタンス化できず、静的メソッドまたはフィールドを提供しません。プライベートコンストラクターがあり、静的メソッドまたはフィールドがないクラスは使用できません。

これらの警告を無視する必要がありますか?

別の質問:クラス内のプライベートフィールドPizzaBuilderが重複しています。プライベートフィールドの数が増えると、これは厄介になります。それを回避する方法はありますか?

4

2 に答える 2

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() {
}
}
于 2011-05-30T12:20:50.623 に答える
1

クラスPizzaとBuilderのプライベートフィールドは重複しています。プライベートフィールドの数が増えると、これは厄介になります。それを回避する方法はありますか?

私は個人的に、すべてのフィールドを含む3番目のプライベート静的値オブジェクトクラスを使用してこれを回避し、ビルダーとメインクラスの両方で使用します(フィールドアクセスは委任によって処理されます)。確かに、これは行数/クラス数を増やすことになるかもしれませんが、ビルダーが多数のフィールドとチェックで複雑になる場合に非常に貴重です。

また、必須フィールドを使用して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

}
于 2011-05-30T09:41:53.020 に答える