我有几个类(class),如下所示

public class TrueFalseQuestion implements Question{
    static{
        QuestionFactory.registerType("TrueFalse", "Question");
    }
    public TrueFalseQuestion(){}
}

...
public class QuestionFactory {

 static final HashMap<String, String > map =  new HashMap<String,String>();

 public static void registerType(String questionName, String ques ) {
     map.put(questionName, ques);
     }
 }



public class FactoryTester {
    public static void main(String[] args) {
        System.out.println(QuestionFactory.map.size());
        // This prints 0. I want it to print 1
    }
}

如何更改TrueFalseQuestion类,以便始终运行静态方法,以便在运行main方法时得到1而不是0?我不想对主要方法进行任何更改。

我实际上是在尝试实现子类向工厂注册的工厂模式,但是我简化了此问题的代码。

最佳答案

要向工厂注册TrueFalseQuestion类,需要调用其静态初始化程序。要执行TrueFalseQuestion类的静态初始化器,需要在调用QuestionFactory.map.size()之前引用该类或通过反射将其加载。如果要保持不变main方法,则必须引用它或通过反射将其加载到QuestionFactory静态初始值设定项中。我不认为这是个好主意,但我只回答您的问题:)如果您不介意QuestionFactory知道所有实现Question来构造它们的类,则可以直接引用它们或通过加载它们反射。就像是:

public class QuestionFactory {

 static final HashMap<String, String > map =  new HashMap<String,String>();

 static {
    this.getClassLoader().loadClass("TrueFalseQuestion");
    this.getClassLoader().loadClass("AnotherTypeOfQuestion"); // etc.
 }

 public static void registerType(String questionName, String ques ) {
     map.put(questionName, ques);
     }
 }

确保map的声明和构造在static块之前。如果您不希望QuestionFactoryQuestion的实现有任何了解,则必须在QuestionFactory加载的配置文件中列出它们。我认为可以做的另一种(可能是疯狂的)方法是在整个类路径中查找实现Question的类:)如果所有实现Question的类都需要属于同一个包,那可能会更好—注意:我不支持此解决方案;)

我不认为在QuestionFactory静态初始值设定项中执行任何此操作的原因是,像TrueFalseQuestion这样的类具有自己的静态初始值设定项,这些初始值设定项会调用QuestionFactory,这当时是一个未完全构造的对象,仅是在问麻烦。一个配置文件仅列出您希望QuestionFactory知道如何构造的类,然后在其构造函数中注册它们是一个很好的解决方案,但这将意味着更改main方法。

09-25 18:50