Interesting problem. I've heard this referred to as the "Multiton" pattern.
Dhanji. On Fri, Oct 15, 2010 at 3:27 AM, Fred Faber <ffa...@faiser.com> wrote: > Basically you have a factory that should return a singleton instance for > each unique string value passed into it? > > FactoryProvider won't do this for you out of the box, as it will create a > new instance per invocation (as you've illustrated). > > What I would do in this case is to decorate your factory with an > implementation that controls singletonness: > > interface CacheFactory { > // This can be named anything you want, not just "create" > NamedCache create(String name); > } > > class CachingCacheFactory implements CacheFactory { > > private final CacheFactory underlyingFactory; > > // > http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/MapMaker.html > private final Map<String, NamedCache> caches = new MapMaker() > .makeComputingMap(new Function<String, NamedCache>(){ > @Override public NamedCache apply(String name) { > return underlyingFactory.create(name); > } > }); > > @Inject > CachingCacheFactory { > @AlwaysCreatesNewInstances CacheFactory cacheFactory) { > this.underlyingFactory = cacheFactory; > } > > @Override > NamedCache create(String name) { > return caches.get(name); > } > } > > > * * * > > public class YourModule extends AbstractModule { > > @Override protected void configure() { > // as an alternative to binding this as a singleton, you could > inject the map of caches > // as a singleton instance. 6 or 1/2 dozen, unless you want to > unittest your > // implementation, in which case you'll want to inject the singleton > map > bind(CacheFactory.class) > .to(CachingCacheFactory.class) > .in(Singleton.class); > > // > http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/assistedinject/FactoryModuleBuilder.html > // this binds a "CacheFactory" instance, annotated with > @AlwaysCreatesNewInstances, to > // a default factory implementation which will return instances of > NamedCacheLocal when > // its create() method is invoked > install(new FactoryModuleBuilder() > .implement(NamedCache, NamedCacheLocal) > .build(Key.get(NamedCache.class, > AlwaysCreatesNewInstances.class)); > } > } > > That should do the trick. > > -Fred > > > On Thu, Oct 14, 2010 at 4:25 AM, Sondre Bjornebekk < > sondre.bjorneb...@gmail.com> wrote: > >> Hi, >> >> Trying to use assisted inject and find it pretty neat, the minor >> detail is that it does not quite work for me yet :-) >> >> I have created a Map wrapper to ease switching of caches (typically to >> something like Coherence) for my application. I want the Map to be >> returned "in a Singleton scope, based on the value of the (assisted) >> parameter". I am doing: >> >> bind(CacheFactory.class).toProvider( >> FactoryProvider.newFactory(CacheFactory.class, >> NamedCacheLocal.class) ); >> >> And I have: >> /** >> * A factory for named caches, that later might hide its >> implementation using a cluster wide storage. >> */ >> >> public interface CacheFactory { >> //had to be named create to work with guice assisted inject, so >> renamed from getNamedCache >> public NamedCache create(String name); >> } >> >> public interface NamedCache<K,V> extends Map<K,V> { >> public int getHitPercent(); >> public String getHitPercentString(); >> ... >> } >> >> /** >> * A named cache with a local map as implementation for storage. >> */ >> >> public class NamedCacheLocal<K,V> implements NamedCache<K,V> { >> ... >> >> /** >> * Constructs a NamedCacheLocal with its dependencies. >> */ >> @Inject >> public NamedCacheLocal(@Assisted String cacheName) { >> ... >> } >> >> I have this (failing) unit test that checks that the same cache is >> used for the same name: >> >> System.out.println("doing put / get test"); >> NamedCache<String,String> namedCache = >> namedCacheFactory.create("myCache"); >> namedCache.put("fisk","fesk"); >> for(int i=0;i<10; i++){ >> Object o = namedCache.get("non-hit"); >> namedCache.put("test"+i,"testval"+i); >> } >> Object hit = namedCache.get("fisk"); >> System.out.println("cache " + namedCache + " delivered value " >> + hit + " to a hit percent of " + namedCache.getHitPercentString()); >> assertTrue(namedCache.getHitPercent() > 8 && >> namedCache.getHitPercent() < 10); >> NamedCache<String,String> namedCacheWithSameName = >> namedCacheFactory.create("myCache"); >> for(int i=0;i<10; i++){ >> String val = namedCacheWithSameName.get("test"+i); >> System.out.println("got val from cache: " + val); >> } >> //should have used the same reference, thus hit pct now higher >> System.out.println("done with cache " + >> namedCacheWithSameName); >> assertTrue(namedCache.getHitPercent() > 10); >> assertTrue(namedCache.equals(namedCacheWithSameName)); >> >> >> So is the thing I put in quotation marks in the intro ("in a Singleton >> scope, based on the value of the (assisted) parameter") even possible >> just by Guice config, or do I have to go two steps back and one >> forward and just implement the CacheFactory myself with this logic? >> The first thing I tried was >> >> bind( CacheFactory.class ). >> toProvider( FactoryProvider.newFactory(CacheFactory.class, >> NamedCacheLocal.class) ) . >> in ( Singleton.class ); >> >> But that (of course) just gives me a singleton CacheFactory, not the >> NamedCacheLocal "singleton" based on the assisted factory parameter. >> >> Cheers, >> >> Sondre >> >> -- >> You received this message because you are subscribed to the Google Groups >> "google-guice" group. >> To post to this group, send email to google-gu...@googlegroups.com. >> To unsubscribe from this group, send email to >> google-guice+unsubscr...@googlegroups.com<google-guice%2bunsubscr...@googlegroups.com> >> . >> 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 google-gu...@googlegroups.com. > To unsubscribe from this group, send email to > google-guice+unsubscr...@googlegroups.com<google-guice%2bunsubscr...@googlegroups.com> > . > 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 google-gu...@googlegroups.com. To unsubscribe from this group, send email to google-guice+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.