私の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 にバインドするには、ここで何が必要ですか?