增强java中的工厂模式

发布于 2024-08-28 07:19:33 字数 1045 浏览 4 评论 0原文

我正在尝试使用工厂模式来创建一个 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)

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

I am trying to use a factory pattern to create a QuestionTypeFactory where the instantiated classes will be like MultipleChoice, TrueFalseQuestion etc.

The factory code looks something like this

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.");
}
}

This works ok for now. If I want to add another question type I will need to modify the factory class and I do not want to do that.

How can I set it up so that each question class registers itself with the Factory so that when I add a new question type, I do not have to change the code for the factory? I am a bit new to java and am not sure how to do this.

Edit

Additional Information

All the question classes implement an IQuestion interface. I am looking for a way to implement a method like

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

so that I can call this method from a static block from my classes so that when I add a new question type, I will not have to change or add any code in the Question Factory. I know I would have to change the current implementation to make it generic. I am not sure the method that I wrote above is correct in terms of its arguments syntactically or not but it shows what I want in concept.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

想你的星星会说话 2024-09-04 07:19:33

您也许可以通过 Reflection API(Class 的东西)使用您所展示的 register 方法来做到这一点。

我对 Java Reflection 不够精通,无法编写更有用的答案,但如果您寻找一些 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
}

You can probably do that with the register method you've shown, through the Reflection API (that Class thingy).

I am not proficient enough with Java Reflection to write a more helpful answer, but if you look for some getConstructor method or something you'll probably get there.

To call that method you should do something like (note the .class syntax):

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

EDIT Ah, whatever, I have the time to investigate. Try this:

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();
    }
}

I haven't compiled this, but it should work, or at least guide you in the right direction. For this to work the Question implementations must have a constructor without arguments.

Because you're using a static factory (aka, object-oriented global variables) you can make questions register themselves in their static initializer.

public class TrueFalseQuestion implements Question {
    static {
        QuestionFactory.registerType(QuestionType.TrueFalse, TrueFalseQuestion.class);
    }
    // Whatever else goes here
}
最舍不得你 2024-09-04 07:19:33

一种可能性:

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();
}

One possibility:

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(); 
    }
}

Of course, this gets rid of the factory and assumes all your questions have no-args constructors, but as far as I can tell, it covers all the cases of the code sketch above. If construction for the particularly classes is more complicated, you can always setup something like:

public enum QuestionType {
    TrueFalse { public Question createQuestion() { /* construction logic goes here */ } }
    public abstract Question createQuestion();
}
吖咩 2024-09-04 07:19:33

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

I'm pretty sure you just want to create a method on your enum type which will return the appropriate Question object. So anytime someone adds an enum value to QuestionType they will also have to update the method. Doesn't solve your problem of having to update that method though...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文