是我的构建器实现违反了可变性

时间:2015-10-29 14:40:10

标签: java optimization mutability

我想知道我对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;
        }

    }

}

或者我应该调整什么来解决可变性问题。有什么建议吗?

2 个答案:

答案 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。

在单线程应用程序中,你会没事的。