1

私のguiceモジュールには、以下に示すような複数のファクトリがあります:

install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));

両方のファクトリには、支援された要素を取る次の create メソッドがあります。

Ferrari create(@Assisted Element partsElement);

Mercedes create(@Assisted Element partsElement);

CarChooser クラスでは、以下に示すように Ferrari または Mercedes のインスタンスを取得します。

@Inject 
public CarChooser(FerrariFactory ferrariFactory , MercedesFactory mercedesFactory )
{
        this.ferrariFactory = ferrariFactory;
        this.mercedesFactory = mercedesFactory;
} 

同じクラスの中で:

if(type.equals("ferrari"))
    ferrariFactory.create(partsElement);
else if (type.equals("mercedes"))
    mercedesFactory.create(partsElement);
...

今、私がしようとしているのは、この CarChooser クラスを拡張用に開いているが、変更用に閉じていることです。つまり、別の Factory を追加する必要がある場合、それを変数として宣言し、コンストラクターに追加し、対応する新しい型に別の if 句を追加する必要はありません。ここで ServiceLoader を使用し、すべてのファクトリ (FerrariFactory、MercedesFactory など) によって実装されるインターフェイス CarFactory を宣言し、すべての実装に getCarType メソッドを含めることを計画していました。しかし、Service Loader を使用して create メソッドを呼び出すにはどうすればよいでしょうか?

ServiceLoader<CarFactory> impl = ServiceLoader.load(CarFactory.class);

for (CarFactory fac: impl) {
     if (type.equals(fac.getCarType()))
         fac.create(partsElement);
     }
}

それが機能する場合は正しい方法です(これが機能するかどうかさえわかりません)。または、同じことを行うより良い方法はありますか?

投稿に対する最初のコメントのおかげで、 MapBinder を使用したいことがわかりました。FerrariFactory と MercedesFactory の両方で拡張された CarFactory を作成しました。だから私は以下を追加します:

MapBinder<String, CarFactory> mapbinder = MapBinder.newMapBinder(binder(), String.class, CarFactory.class);

mapbinder.addBinding("Ferrari").to(FerrariFactory.class);
mapbinder.addBinding("Mercedes").to(MercedesFactory.class);

しかし、上記のコードの .to 部分は抽象クラスであるため、FerrariFactory がどの実装にもバインドされていないという初期化エラーが発生します。FactoryModuleBuilder で宣言された正しい Assisted Inject Factory にバインドするには、ここで何が必要ですか?

4

1 に答える 1