我使用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个警告:
我应该忽略这些警告吗?
另一个问题:班级Pizza
和Builder
中的私人字段是重复的。当私人领域的数量越来越大时,这将是烦人的。有什么方法可以避免吗?
答案 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
}