我想知道我对QuestionBuilder的实现是否违反了可变性。
public class Question<T extends Serializable> implements Serializable {
private QuestionHolder<T> questionHolder;
private Question(QuestionHolder<T> questionHolder) {
this.questionHolder = questionHolder;
}
public String getId() {
return questionHolder.id;
}
public int getOrder() {
return questionHolder.order;
}
public QuestionType getType() {
return questionHolder.type;
}
public boolean isImmediate() {
return questionHolder.immediate;
}
public boolean isMandatory() {
return questionHolder.mandatory;
}
public List<T> getSelectedValues() {
return questionHolder.selectedValues;
}
public List<T> getPossibleValues() {
return questionHolder.possibleValues;
}
private static final class QuestionHolder<T extends Serializable> {
private String id;
private int order = 0;
private QuestionType type;
private boolean immediate;
private boolean mandatory;
private List<T> selectedValues;
private List<T> possibleValues;
}
public static final class QuestionBuilder<T extends Serializable> implements Builder<Question<T>> {
private QuestionHolder<T> questionHolder;
public QuestionBuilder(String id) {
questionHolder = new QuestionHolder<>();
questionHolder.id = id;
}
public QuestionBuilder withOrder(int order) {
questionHolder.order = order;
return this;
}
public QuestionBuilder withType(QuestionType questionType) {
questionHolder.type = questionType;
return this;
}
public QuestionBuilder withImmediate(boolean immediate) {
questionHolder.immediate = immediate;
return this;
}
public QuestionBuilder withMandatory(boolean mandatory) {
questionHolder.mandatory = mandatory;
return this;
}
public QuestionBuilder withSelectedValues(List<T> selectedValues) {
questionHolder.selectedValues = selectedValues;
return this;
}
public QuestionBuilder withPossibleValues(List<T> possibleValues) {
questionHolder.possibleValues = possibleValues;
return this;
}
public Question<T> build() {
Question<T> question = new Question<>(questionHolder);
questionHolder = null;
return question;
}
}
}
或者我应该调整什么来解决可变性问题。有什么建议吗?
答案 0 :(得分:0)
据我所知,您正在使用每个构建器调用来更改QuestionHolder。 我会做的是:
1)将QuestionHolder中的所有属性设为私有,并且根本不创建任何setter。
2)将每个属性存储在构建器实例中,并在构建器的构建方法中创建一个新的QuestionHolder实例。
例如:
public Question<T> build() {
// DO ALL THE VALIDATIONS NEEDED
QuestionHolder holder = new QuestionHolder(id, order, type, inmediate, mandatory, selectedValues, possibleValues);
return new Question<>(questionHolder);
}
使用这些方法,您将改变构建器,但这对构建器模式是可行的。显然,每次要创建问题时,都需要创建一个新的Builder实例。如果你想一遍又一遍地使用相同的Builder,你可能需要在其中存储某种结构(例如,由Id标识的地图)。
答案 1 :(得分:0)
如果您担心线程安全,那么此处的代码不一定是线程安全的。
一个线程可能会调用build()并返回一个指向QuestionHolder的Question。尽管build()将持有者设置为null,但另一个线程可能看不到null,而是看到该字段的旧值。如果那个其他线程调用了你的任何setter,它可能会改变Question类已经访问过的Holder。
在单线程应用程序中,你会没事的。