augment the factory pattern in java

99封情书 提交于 2019-12-03 04:49:38

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
}

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

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...

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!