@Sam:
Yes, the Impl can be changed throughout the lifetime of the project,
so I will need some sort of Factory. I was simply hoping there was a
better way of having Guice provide it. I assume with your 2nd
suggestion, you're talking about something like this?
class ServiceFactory {
@Inject ServiceImplA serviceImplA;
@Inject ServiceImplB serviceImplB;
public Service get( int type ) {
if ( type == 1 ) {
return serviceImplA;
} else if ( type == 2 ) {
return serviceImplB;
}
return null;
}
}
That works, although I don't know if I'm fond of requiring that all
implementations be instantiated each time the ServiceFactory is
instantiated.
@Gary:
The "type" is external to the application. I've simplified the use
case obviously, but the client is an object that gets spun up during
an HTTP request. The underlying dependencies (impls) that it needs
will depend on what's in the request. Think Command pattern.
Your builder pattern would work great if I could pass the type to the
get() method, rather than to the provider constructor. But Guice
doesn't support that as a valid Provider<T> implementation.
@Brian:
Can you give me an example of using dynamic proxies, as you explained?
This seems like a fairly common use case, so I'm surprised there isn't
a better pattern to handle it. Thanks everyone for your prompt
responses so far.
Ryan
On Nov 18, 8:38 am, Gary Pampara <[email protected]> wrote:
> Agreed the state could be a problem. You could probably get around it
> by directly passing in the value to avoid managing the state.
>
> Would naturally be great to find a solution that "is always best".
>
>
>
> On Wed, Nov 18, 2009 at 5:31 PM, Brian Pontarelli <[email protected]>
> wrote:
> > Just need to be careful of state and provider use if you go with a builder
> > pattern.
>
> > Another way I've handled this in the past is using dynamic proxies that use
> > the method parameters to perform a lookup. In the end, all the solutions
> > I've used are the same. There is at least one level of indirection and
> > someone has to perform a lookup or build a new instance (i.e. a provider).
> > In the lookup case the Injector can be used to perform the lookup. In the
> > provider case I've used post-inject after instantiation or pre-injection of
> > the provider.
>
> > -bp
>
> > On Nov 18, 2009, at 8:23 AM, Gary Pampara wrote:
>
> >> Sorry I see now what you mean. Where do you get the information
> >> regarding the 'type' so that the factory can create the needed
> >> instance?
>
> >> I solved this a while ago in a project using the builder pattern. This
> >> is a trivial example, but it seems to work. If anyone has a better way
> >> of doing this, I'd appreciate the advice.
>
> >>http://pastie.org/704247
>
> >> On Wed, Nov 18, 2009 at 4:38 PM, Sam Berlin <[email protected]> wrote:
> >>> Will there always be one implementation and only one implementation for
> >>> the
> >>> lifetime of the project? If so, can you decide upon that implementation
> >>> during runtime before the Injector is created? If so, include the
> >>> appropriate module to bind the ServiceImpl you want based on the
> >>> configuration. If the impl can change throughout the lifetime (because
> >>> users can request different types based on the 'type'), then you'll
> >>> absolutely need some form of indirection (in your code the Factory
> >>> provides
> >>> the indirection). If you're concerned about calling new Service1 & new
> >>> Service2, you can use BindingAnnotations to actually bind both kinds of
> >>> Services, the Factory can have both Services injected and then hand out
> >>> the
> >>> appropriate service based on the 'type'.
>
> >>> Sam
>
> >>> On Wed, Nov 18, 2009 at 12:02 AM, Ryan <[email protected]> wrote:
>
> >>>> Hello everyone,
>
> >>>> I'm new to Guice (really enjoying it, by the way), but have come up
> >>>> against a need and I'm not sure the most Guice-appropriate way to do
> >>>> it. Done a lot of searching (including in this group), but am not
> >>>> sure I found the solution. (Or perhaps I just didn't understand it.)
> >>>> In any case, my question is how to select an implementation based on
> >>>> some runtime value. For reference, a standard factory solution would
> >>>> look like:
>
> >>>> class ServiceFactory {
> >>>> public static Service get(int type) {
> >>>> if(type == 1) { return new ServiceImpl1(); }
> >>>> else if (type == 2) { return new ServiceImpl2(); }
> >>>> }
> >>>> }
>
> >>>> class Client {
> >>>> public void process(int type) {
> >>>> Service service = ServiceFactory.get(type);
> >>>> }
> >>>> }
>
> >>>> Feels too service locator-y. But I can think of no way to do this in
> >>>> Guice except to inject the factory:
>
> >>>> class Client {
> >>>> �...@inject
> >>>> ServiceFactory factory;
>
> >>>> public void process(int type) {
> >>>> Service service = factory.get(type);
> >>>> }
> >>>> }
>
> >>>> class ServiceFactoryProvider implements Provider<ServiceFactory> {
> >>>> �...@override
> >>>> public ServiceFactory get() {
> >>>> return new ServiceFactory();
> >>>> }
> >>>> }
>
> >>>> class MyModule extends AbstractModule {
> >>>> �...@override
> >>>> protected void configure() {
> >>>> bind(Client.class);
> >>>> }
> >>>> }
>
> >>>> What am I missing here? What's the proper way to implement this with
> >>>> Guice? I don't think BindingAnnotations will work for me here,
> >>>> because the implementation is decided upon at runtime, but feel free
> >>>> to correct me.
>
> >>>> Thank you!
> >>>> Ryan
>
> >>>> --
>
> >>>> 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=.
>
> >>> --
>
> >>> 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=.
>
> >> --
>
> >> 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
> >> athttp://groups.google.com/group/google-guice?hl=.
>
> > --
>
> > 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
> > athttp://groups.google.com/group/google-guice?hl=.
--
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=.