5

我正在尝试使用工厂模式来创建 QuestionTypeFactory,其中实例化的类将类似于 MultipleChoice、TrueFalseQuestion 等。

工厂代码看起来像这样

class QuestionFactory {
    public enum QuestionType {
        TrueFalse,
        MultipleChoice,
        Essay
    }

public static Question createQuestion(QuestionType quesType) {
    switch (quesType) {
        case TrueFalse:
            return new TrueFalseQuestion();
        case MultipleChoice:
            return new MultipleChoiceQuestion();
        case Essay:
            return new EssayQuestion();
    }
    throw new IllegalArgumentException("Not recognized.");
}
}

现在这工作正常。如果我想添加另一个问题类型,我需要修改工厂类,我不想这样做。

如何设置它,以便每个问题类都向工厂注册,这样当我添加新的问题类型时,我不必更改工厂的代码?我对java有点陌生,不知道该怎么做。

编辑

附加信息

所有的问题类都实现了一个 IQuestion 接口。我正在寻找一种方法来实现类似的方法

public static void registerType(QuestionType quesType, Class<IQuestion> ques)

这样我就可以从我的类的静态块中调用这个方法,这样当我添加一个新的问题类型时,我就不必在问题工厂中更改或添加任何代码。我知道我必须更改当前的实现以使其通用。我不确定我上面写的方法在语法上是否正确,但它显示了我想要的概念。

4

3 回答 3

6

您可以通过反射 API(那个东西)使用您显示的注册方法来做到这一点Class

我对 Java 反射不够精通,无法编写更有用的答案,但是如果您寻找某种getConstructor方法或某些东西,您可能会到达那里。

要调用该方法,您应该执行以下操作(注意.class语法):

QuestionFactory.registerType(QuestionType.TrueFalse, TrueFalseQuestion.class);

编辑啊,无论如何,我有时间调查。尝试这个:

public class QuestionFactory {
    static final Map<QuestionType, Constructor<? extends Question>> map =
        new HashMap<QuestionType, Class<? extends Question>>();

    public static void registerType(QuestionType quesType, Class<? extends Question> ques) {
        map.put(quesType, ques.getConstructor());
    }

    public static Question createQuestion(QuestionType quesType) {
        return map.get(quesType).newInstance();
    }
}

我还没有编译这个,但它应该可以工作,或者至少可以引导你朝着正确的方向前进。为此,问题实现必须有一个不带参数的构造函数。

因为您使用的是静态工厂(又名,面向对象的全局变量),所以您可以让问题在其静态初始化程序中注册。

public class TrueFalseQuestion implements Question {
    static {
        QuestionFactory.registerType(QuestionType.TrueFalse, TrueFalseQuestion.class);
    }
    // Whatever else goes here
}
于 2010-04-06T03:02:15.167 回答
2

一种可能:

public enum QuestionType {
    TrueFalse(TrueFalseQuestion.class),
    MultipleChoice(MultipleChoiceQuestion.class),
    Essay(EssayQuestion.class)

    private final Class<? extends Question> implementationType;
    QuestionType(Class<? extends Question> implementationType) {
       this.implementationType = implementationType;
    }

    public Question createQuestion() { 
       return implementationType.newInstance(); 
    }
}

当然,这摆脱了工厂并假设您所有的问题都有无参数构造函数,但据我所知,它涵盖了上面代码草图的所有情况。如果特定类的构造更复杂,您始终可以设置如下内容:

public enum QuestionType {
    TrueFalse { public Question createQuestion() { /* construction logic goes here */ } }
    public abstract Question createQuestion();
}
于 2010-04-06T03:09:09.127 回答
0

我很确定您只想在枚举类型上创建一个方法,该方法将返回适当的 Question 对象。因此,每当有人向 QuestionType 添加枚举值时,他们也必须更新该方法。虽然不能解决您必须更新该方法的问题......

于 2010-04-06T02:44:30.747 回答