On Fri, Aug 21, 2009 at 11:08 AM, cpea<[email protected]> wrote:
>
> I've seen various flavors of this question from other people but still
> don't feel like I understand how to solve it. Any input would be
> greatly appreciated.
>
> How can I use Guice to create the different instances of the
> calculators?

When you create your bindings, don't tell Guice that this is a
singleton.  Then, Guice will create a new instance for each user.

> Or in this case, do I even NEED to use Guice to create
> the calculator instances since this is a factory. Guice would just
> inject the needed dependencies to the factory. I'm confused about
> "Guice replacing all instances of 'new'" in our code. Does that hold
> true everywhere or are there places where you would expect to 'new' a
> class?

Think about things from the perspective of your calling user for a
moment, and you realize:

* There is no need for the calling user to know whether
  the calculator is a singleton or not.

* There is no need for the calling user to know
  how the calculator got created (factory, service
  lookup, or some other mechanism).

In addition, from the calculator implementor's point of view, you
don't have to waste the effort to create a factory if you don't need
one.  You can change your mind later (singleton to per request,
instance to provider) later as well, with zero impact on the calling
users.  Plus, it's much easier to set up unit tests without having to
mock both a calculator implementation and a factory.

>
> public class CalculatorFactory {
>
>   private final Map<UserGroup, ICalculator> m_calculators;
>
>   public CalculatorFactory(SomeObject dependency1, SomeObject
> dependency2, SomeObject dependency3) {
>         m_calculators = new HashMap<UserGroup, ICalculator>();
>         m_calculators.put(UserGroup.A, new ACalculator(dependency1,
> dependency2, dependency3);
>         m_calculators.put(UserGroup.B, new BCalculator(dependency1);
>         m_calculators.put(UserGroup.C, new CCalculator(dependency1);
>   }
>
>   // Depending on which group a user belongs to,
>   // a different type of calculator will be returned
>   public ICalculator loadCalculator(UserGroup userGroup) {
>           return m_calculators.get(userGroup);
>   }
>
> }

One way you could make this either-or kind of choice would be to
provide a "binding annotation" that a caller can also use to tell
Guice what kind of calculator it needs.  For example, if you have two
groups ("Mechanical" and "Electric") which determines which kind they
need, one caller might say:

    @Inject @Mechanical Calculator calculator;

while another could say:

    @Inject @Electric Calculator calculator;

(Sorry, couldn't resist :-).

The other way to deal with conditional creation would be to bind
Calculator to a Provider<Calculator> (a kind of factory) instead.  The
provider would have some way to figure out what group the user is
(perhaps through getting a User object injected to it), Then, Guice
will call the provider's get() method when it needs an instance
(optionally injecting things into the provider class as needed).

Again, note that the *user* of a Calculator need not understand how
the right instance was picked -- it just gets to worry about actually
using it.

Craig McClanahan

--~--~---------~--~----~------------~-------~--~----~
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