2

ここで説明されているように(例を使用して)Factoryパターンについて明確にしようとしています: http://www.oodesign.com/factory-pattern.html

「リフレクションなしのクラス登録」の例を実装しようとすると、null ポインター例外が発生します。これは、ここで説明されているものと同じです。

クラス登録を伴うファクトリ メソッド パターンが nullpointer 例外を生成する

Null ポインター例外が発生する理由 (HashMap が使用されるまでにデータが取り込まれていない) を理解しており、 Factory実装内のメインブロックまたは静的ブロックでclass.forNameを使用して修正できることを知っています。

しかし、それはこのパターンを使用する目的を無効にしませんか? 作成中のオブジェクトが登録を行ったという考えだと思いました-静的ブロックを強制的に実行するためにクラスを手動でロードする必要がある場合、これはOpen Close Principleに違反しませんか?

コード例は次のとおりです。

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

}

前述のように、これを機能させるには、これを Main または WidgetFactory クラスに配置します。

static {
    try {
        Class.forName(WidgetA.class.getName());
        Class.forName(WidgetB.class.getName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace(System.err);
    }
}

繰り返しになりますが、新しい Widget サブクラスが追加されるたびに Main クラスまたは WidgetFactory クラスを更新することなく、このパターンをどのように実装するか、またはこのパターンを機能させるためのテクニックを共有してください。

ご協力ありがとうございました!

4

1 に答える 1