Reputation: 8816
Let's say I have a ThirPartyModule
third-party Module which binds lots of components that I can then use in my application :
Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule());
If I want to modify the implementation classes used for some bindings in that Module, what is the best approach?
For example, let's say ThirPartyModule
performs that binding :
bind(WidgetInterface.class).to(DefaultWidgeImpl.class).in(Scopes.SINGLETON);
and I want to be able to change the DefaultWidgeImpl
class for MyWidgetImpl
class. I know I could use an overriding Module, and simply rebind the WidgetInterface
key. But what if ThirPartyModule
binds a lot of things using that same Widget implementation? I may not want to have to rebind each of them!
So I'm trying to find the best solution to be able to specify the implementation class to use, without having the rebind all the components depending on it.
I guess ThirPartyModule
could first create a getter method for the implementation class :
bind(WidgetInterface.class).to(getWidgetImpClass()).in(Scopes.SINGLETON);
protected Class<? extends WidgetInterface> getWidgetImpClass() {
return DefaultWidgeImpl.class;
}
and then the application could override the getWidgetImpClass()
method :
Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule() {
@Override
protected Class<? extends WidgetInterface> getWidgetImpClass() {
return MyWidgetImpl.class;
}
});
I also though about passing the implementation class to the constructor of the Module :
Injector guice = Guice.createInjector(new MyAppModule(), new ThirPartyModule(MyWidgetImpl.class));
I'd like to know if there is an accepted pattern to customize such third-party Modules? Let's say I can ask the Modules to be written in a specific way if it helps them to be customizable.
Upvotes: 1
Views: 588
Reputation: 12932
Here's how I would do it:
public class ThirdPartyModule extends AbstractModule {
@Override
protected void configure() {
// CoolWidget --
// \
// > WidgetInterface -> DefaultWidgetImpl
// /
// AwesomeWidget
OptionalBinder.newOptionalBinder(binder(), WidgetInterface.class)
.setDefault()
.to(DefaultWidgetImpl.class);
bind(CoolWidget.class).to(WidgetInterface.class);
bind(AwesomeWidget.class).to(WidgetInterface.class);
// etc.
}
}
public class MyAppModule extends AbstractModule {
@Override
protected void configure() {
OptionalBinder.newOptionalBinder(binder(), WidgetInterface.class)
.setBinding()
.to(CustomWidgetImpl.class);
}
}
By making all the bindings go indirectly through the WidgetInterface
key, you only need to override that one binding.
Upvotes: 2