I have a factory I like to reimplement using Guice:
enum MyObjects { OBJECT1, OBJECT2, ... }
class Object1 implements SomeInterface { ... }
class Object2 implements SomeInterface { ... }
...
class Factory {
public static SomeInterface createObject(MyObjects obj) {
switch (obj) {
case OBJECT1: return new Object1();
case OBJECT2: return new Object2();
...
}
}
Is there an easy way to implement it? Something like Provider.get(parameter) and using bindings to define which object should be used in each case?
You have several options here.
1. since you use an enum
to distinguish between implementations, then you have a finite number of implementations that you can define each with their own binding, provided you use an annotation during injection
public @interface SomeInterfaceKind {
MyObjects value();
}
in your Module
:
bind(SomeInterface.class)
.annotatedWith(new SomeInterfaceKindImpl(MyObjects1.OBJECT1)
.to(Object1.class);
...
Then in classes to be injected:
@Inject void setSomeInterface(
@SomeInterfaceKind(MyObjects.OBJECT1) SomeInterface object) {...}
Here you have to define SomeInterfaceKindImpl
class that implements SomeInterfaceKind
(yes, it's possible to extend an annotation!) For more details, take a look at how Named
is implemented in Guice.
2. You can also use Guice MapBinder as follows (I find it simpler to implement)
In your Module:
MapBinder.newMapBinder(MyObjects.class, SomeInterface.class)
.addBinding(MyObjects.OBJECT1).to(Object1.class);
MapBinder.newMapBinder(MyObjects.class, SomeInterface.class)
.addBinding(MyObjects.OBJECT2).to(Object2.class);
Then in injected methods:
@Inject void setSomeInterface(Map<MyObjects, SomeInterface> map) {
SomeInterface object1 = map.get(MyObjects.OBJECT1);
...
}
You can also use assisted inject
public interface Factory {
public Object1 createObject1(String param1);
public Object2 createObject2(Date param2);
}
public class Object1 {
@AssistedInject
public Object1(String param1) {
// do something
}
}
public class Object2 {
@AssistedInject
public Object2(Dateparam2) {
// do something
}
}
Then in your module
install(new FactoryModuleBuilder()
.implement(Object1.class, Object1.class)
.implement(Object2.class, Object2.class)
.build(Factory.class));
Then you can use the factory wherever you need it
@Inject
private Factory factory;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With