事实上,我想问一下我的方法是否正确,因为我可能不应该在这里使用构建器模式。
我目前有以下课程CsvItem
:
public class CsvItem {
private CsvItemGroup group;
private CsvItemEntity entity;
private String att1;
private String att2;
private String att3;
private String att4;
private String att5;
private String att6;
private String att7;
private String att8;
CsvItem(
CsvItemGroup group,
CsvItemEntity entity,
String att1,
String att2,
String att3,
String att4,
String att5,
String att6,
String att7,
String att8) {
this.group = group;
this.entity = entity;
this.att1 = att1;
this.att2 = att2;
this.att3 = att3;
this.att4 = att4;
this.att5 = att5;
this.att6 = att6;
this.att7 = att7;
this.att8 = att8;
}
}
我有一些从CsvItem
延伸的子类,CsvItemA
:
public class CsvItemADW extends CsvItem {
public CsvItemADW(CsvItemEntity entity,
String att1,
String att2,
String att3,
String att4,
String att5,
String att6,
String att7,
String att8) {
super(CsvItemGroup.A, entity, att1, att2, att3, att4, att5, att6, att7, att8);
}
}
这种方法确实有效,如果我有另一个类CsvItemB
,我只需修改构造函数即可发送CsvItemGroup.B
。
这里的问题是我想在超类中使用构建器模式,以便仅使用我需要的属性,并且无法创建具有空值或空值的构造函数。
我面临的问题是我不想重复代码,如果我在子类中使用构建器模式,我会有很多重复的代码。请注意,超类和子类具有相同的属性,唯一改变的是itemGroup
。
构建器模式用法示例:
public class CsvItem {
private final CsvItemGroup group;
private final CsvItemEntity entity;
private final String att1;
private final String att2;
private final String att3;
private final String att4;
private final String att5;
private final String att6;
private final String att7;
private final String att8;
private CsvItem(CsvItemBuilder csvItemBuilder) {
this.group = csvItemBuilder.group;
this.entity = csvItemBuilder.entity;
this.att1 = csvItemBuilder.att1;
this.att2 = csvItemBuilder.att2;
this.att3 = csvItemBuilder.att3;
this.att4 = csvItemBuilder.att4;
this.att5 = csvItemBuilder.att5;
this.att6 = csvItemBuilder.att6;
this.att7 = csvItemBuilder.att7;
this.att8 = csvItemBuilder.att8;
}
public static class CsvItemBuilder{
private final CsvItemGroup group;
private final CsvItemEntity entity;
private String att1;
private String att2;
private String att3;
private String att4;
private String att5;
private String att6;
private String att7;
private String att8;
public CsvItemBuilder(CsvItemGroup itemGroup, CsvItemEntity itemEntity) {
this.group = itemGroup;
this.entity = itemEntity;
}
public CsvItemBuilder withAtt1(String att1) {
this.att1 = att1;
return this;
}
public CsvItemBuilder withAtt2(String att2) {
this.att2 = att2;
return this;
}
// ... same with all attX
public CsvItem build() {
return new CsvItem(this);
}
}
}
答案 0 :(得分:5)
这听起来像是用于类层次结构的 Builder模式问题(Effective Java)。你的通用CsvItem就像Book的例子中的Pizza:
public abstract class Pizza {
final Set toppings;
Pizza(Builder<?> builder) {
toppings = builder.toppings.clone();
}
public enum Topping {HAM, MUSHROOM, ONION, PEPPER, SAUSAGE}
abstract static class Builder<T extends Builder> {
EnumSet toppings = EnumSet.noneOf(Topping.class);
abstract Pizza build();
public T addTopping(Topping topping) {
toppings.add(Objects.requireNonNull(topping));
return self();
}
// Subclasses must override this method to return "this"
protected abstract T self();
}
}
然后,您的特定CsvItem就像NyPizza和Calzone:
public class NyPizza extends Pizza {
private final Size size;
private NyPizza(Builder builder) {
super(builder);
size = builder.size;
}
public enum Size {SMALL, MEDIUM, LARGE}
public static class Builder extends Pizza.Builder<Builder> {
private final Size size;
public Builder(Size size) {
this.size = Objects.requireNonNull(size);
}
@Override
public NyPizza build() {
return new NyPizza(this);
}
@Override
protected Builder self() {
return this;
}
}
}
public class Calzone extends Pizza {
private final boolean sauceInside;
private Calzone(Builder builder) {
super(builder);
sauceInside = builder.sauceInside;
}
public static class Builder extends Pizza.Builder<Builder> {
private boolean sauceInside = false; // Default
public Builder sauceInside() {
sauceInside = true;
return this;
}
@Override
public Calzone build() {
return new Calzone(this);
}
@Override
protected Builder self() {
return this;
}
}
}
使用它:
NyPizza pizza = new NyPizza.Builder(SMALL)
.addTopping(SAUSAGE).addTopping(ONION).build();
Calzone calzone = new Calzone.Builder()
.addTopping(HAM).sauceInside().build();
希望它对你有所帮助。