Great... Solved one problem for me.. Thx
Sent from my iPhone
On 18/03/2010, at 01:19, Fred Faber <[email protected]> wrote:
I think you'd be better off using a MapBinder. The boilerplate of
guice essentially disappears, with only your specific configuration
needing to consume a linearly incremental amount of code per new type.
Code below.
regards
-Fred
class FooFactory {
static class FooKey {
final char type;
final boolean inverted;
FooKey(char type, boolean inverted) {
this.type = type;
this.inverted = inverted;
}
// ...override equals/hashCode as need be. most likely
// you already have this type of 'tuple' common class somewhere.
}
private final Map<FooKey, Provider<Foo>> providerMap;
@Inject
FooFactory(Map<FooKey, Provider<Foo>> providerMap) {
this.providerMap = providerMap;
}
Foo get(char type, boolean inverted) {
FooKey fooKey = new FooKey(type, inverted);
//
http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/Preconditions.html
Provider<Foo> fooProvider =
com.google.common.base.Preconditions.checkNotNull(
providerMap.get(fooKey, "No provider found for key:
%s", fooKey));
return fooProvider.get();
}
}
* * *
in your module, simply bind your classes:
public FooModule extends AbstractModule {
@Override
protected void configure() {
bind(FooFactory.class).in(Singleton.class);
addFooBinding('A', TypeAFoo.class);
addFooBinding('B', TypeBFoo.class);
addInvertableFooBinding('C', true, TypeCAFoo.class);
addInvertableFooBinding('C', false, TypeCBFoo.class);
.... etc
}
private addFooBinding(Char type, Class<? extends Foo> fooClass) {
addInvertableFooBinding(type, true, fooClass);
addInvertableFooBinding(type, false, fooClass);
}
private addInvertableFooBinding(Char type, Boolean inverted,
Class<? extends Foo> fooClass) {
FooKey fooKey = new FooKey(type, inverted);
//
http://google-guice.googlecode.com/svn/trunk/latest-javadoc/com/google/inject/multibindings/MapBinder.html
MapBinder<FooKey, Foo> mapBinder =
MapBinder.newMapBinder(binder(), FooKey.clas, Foo.class);
mapBinder.addBinding(fooKey, fooClass);
}
}
On Wed, Mar 17, 2010 at 11:57 PM, Jason Felice <[email protected]
> wrote:
I just posted this blog article:
http://eraserhead.net/2010/03/creating-boilerplate-with-google-guice/
A note: While it seems to be a peculiar problem, I'm not slamming
Guice, Guice is still a big net win for us!
I post here for thoughts on this problem, and suggestions for
solutions to it.
Excerpt:
There’s plenty of boilerplate that Guice removes, mostly in the
“bean wiring” category, and this is good. Interestingly, there
are areas in which I’ve found myself writing more boilerplate with G
uice, and an instance of this is what I’d like to discuss today.
I work with some people who have become thoroughly disgusted with
OOP and advocate for functional style with immutable data types. I
appreciate functional style with immutable data types, but I must
say that the Strategy pattern is something OOP does well and not
something that FP does nearly as well. I tend to use strategy
pattern quite a bit in our XPay (and in our C++ product, DAS). One
reason to prefer Strategy pattern to switch statements is to have a
single point of control over which strategy implementation to use.
This use case usually conjures itself into being in a Factory method
pattern which has the single switch statement which provides an
instance of the concrete type based on input parameters.
In Guice, you can inject a Provider<Foo> and Guice will
automatically create a type that produces instances of Foo. This is
useful for dependencies. So our factory ends up looking something
like this:
class FooFactory {
private final Provider<TypeAFoo> typeAFooProvider;
private final Provider<TypeBFoo> typeBFooProvider;
private final Provider<TypeCAFoo> typeCAFooProvider;
private final Provider<TypeCBFoo> typeCBFooProvider;
private final Provider<TypeDFoo> typeDFooProvider;
private final Provider<TypeEFoo> typeEFooProvider;
@Inject
public FooFactory(
final Provider<TypeAFoo> typeAFooProvider,
final Provider<TypeBFoo> typeBFooProvider,
final Provider<TypeCAFoo> typeCAFooProvider,
final Provider<TypeCBFoo> typeCBFooProvider,
final Provider<TypeDFoo> typeDFooProvider,
final Provider<TypeEFoo> typeEFooProvider
)
{
this.typeAFooProvider = typeAFooProvider;
this.typeBFooProvider = typeBFooProvider;
this.typeCAFooProvider = typeCAFooProvider;
this.typeCBFooProvider = typeCBFooProvider;
this.typeDFooProvider = typeDFooProvider;
this.typeEFooProvider = typeEFooProvider;
}
public Foo get(char type, boolean inverted) {
switch (type) {
case 'A':
return typeAFooProvider.get();
case 'B':
return typeBFooProvider.get();
case 'C':
if (inverted)
return typeCAFooProvider.get();
else
return typeCBFooProvider.get();
case 'D':
return typeBFooProvider.get();
case 'E':
return typeBFooProvider.get();
default:
throw new FooFactoryException("Can't determine type.");
}
}
};
Ugh!
This is “better” boilerplate than the bean wiring before in that
it hints that we might be able to concoct a general solution; howeve
r, I haven’t yet found it. One solution which I’ve rejected is
the “injecting an injector” solution:
class FooFactory {
private final Injector injector;
@Inject
public FooFactory(final Injector injector) {
this.injector = injector;
}
public Foo get(char type, boolean inverted) {
switch (type) {
case 'A':
return injector.createInstance(TypeAFoo.class);
case 'B':
return injector.createInstance(TypeBFoo.class);
case 'C':
if (inverted)
return injector.createInstance(TypeCAFoo.class);
else
return injector.createInstance(TypeCBFoo.class);
case 'D':
return injector.createInstance(TypeDFoo.class);
case 'E':
return injector.createInstance(TypeEFoo.class);
default:
throw new FooFactoryException("Can't determine type.");
}
}
};
The reason I’ve rejected this approach is that it prevents Guice fro
m checking the entire dependency graph at boot – Guice doesn’t
know which types you are going to create with the injector, and this
has to defeat a lot of it’s validation magic.
--
You received this message because you are subscribed to the Google
Groups "google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected]
.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en
.
--
You received this message because you are subscribed to the Google
Groups "google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected]
.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en
.
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice?hl=en.