I am trying to get clarification around the Factory Pattern as described (with examples) here: http://www.oodesign.com/factory-pattern.html
When I attempt to implement the "class registration without reflection" example I get a null pointer exception. This is the same as has been described here:
factory method pattern with class registration produces a nullpointer exception
I understand why I am getting the null pointer exception (the HashMap is not populated by the time it is being used) and I know that I can fix it by using class.forName in the main or in a static block within the Factory implementation.
But doesn't that defeat the purpose of using this pattern? I thought the idea was that the object being created did the registration - if you are forced to manually load the class to force the static block to run, doesn't this violate the Open Close Principle?
Here is example code:
Main.java
public class Main {
public static void main(String[] args) {
Widget widgetA = WidgetFactory.getInstance().createWidget("WidgetA");
Widget widgetB = WidgetFactory.getInstance().createWidget("WidgetB");
widgetA.doSomething();
widgetB.doSomething();
}
}
Widget.java
public abstract class Widget {
protected abstract Widget createWidget();
public abstract void doSomething();
}
WidgetFactory.java
public class WidgetFactory {
private static WidgetFactory instance;
public static synchronized WidgetFactory getInstance() {
if (instance == null) {
instance = new WidgetFactory();
}
return instance;
}
private HashMap<String, Widget> widgets = new HashMap<>();
public void registerWidget(String id, Widget widget) {
widgets.put(id, widget);
}
public Widget createWidget(String id) {
Widget widget = widgets.get(id).create();
return widget;
}
}
WidgetA.java
public class WidgetA extends Widget {
static {
WidgetFactory.getInstance().registerWidget("WidgetA", new WidgetA());
}
@Override
protected Widget createWidget() {
return new WidgetA();
}
@Override
public void doSomething() {
System.out.println("WidgetA");
}
}
WidgetB.java
public class WidgetB extends Widget {
static {
WidgetFactory.getInstance().registerWidget("WidgetB", new WidgetB());
}
@Override
protected Widget createWidget() {
return new WidgetB();
}
@Override
public void doSomething() {
System.out.println("WidgetB");
}
}
As mentioned earlier, to get it to work I can put this in the Main or the WidgetFactory class:
static {
try {
Class.forName(WidgetA.class.getName());
Class.forName(WidgetB.class.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace(System.err);
}
}
Again, can someone please clarify how this pattern should be implemented or share a technique to make this pattern work without having to update the Main or the WidgetFactory class each time a new Widget subclass is added?
Thank you for your help!