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.

Reply via email to