В моем модуле 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 и объявить интерфейс CarFactory, который будет реализован всеми фабриками (такими как FerrariFactory, MercedesFactory и т. д.), и все реализации будут иметь метод getCarType. Но как я могу вызвать метод create с помощью Service Loader?
ServiceLoader<CarFactory> impl = ServiceLoader.load(CarFactory.class);
for (CarFactory fac: impl) {
if (type.equals(fac.getCarType()))
fac.create(partsElement);
}
}
Правильный ли способ, если он работает (я даже не уверен, сработает ли это). Или есть лучший способ сделать то же самое?
Благодаря первому комментарию к публикации я знаю, что хочу использовать MapBinder. Я написал CarFactory, который расширяется как FerrariFactory, так и MercedesFactory. Поэтому я добавляю следующее:
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?
Set<CarFactory>
в вашем модуле. - person Tavian Barnes   schedule 18.07.2016