Guice - how to implement a factory that returns different implementations

Suppose I have a service called Guice service, and here is its constructor

public GuiceService(IPayment payment) { this.payment = payment; } 

And my code used to create it with Enum

 IPayment payment = new PaymentFactory.create(PaymentType.Cash); NaiveService naiveService = new NaiveService(payment); 

And I had to have a factory implementation somewhere. Something like that

 public IPayment create(PaymentType paymentType) { IPayment cardPayment = null; switch (paymentType) { case Cash: cardPayment = new CashPayment(100); break; case Card: cardPayment = new CardPayment(10, 100); break; } return cardPayment; 

Now I want to use Guice, and I assume that I want to use FactoryModuleBuilder.

  • What is the way to do this if I have another unity of payment.
    (e.g. CardPayment, CashPayment)
    It works for one

     install(new FactoryModuleBuilder() .implement(IPayment.class, CashPayment.class) .build(IPaymentFactory.class)); 
  • How to implement a constructor?
    Will he still receive IPayment? or will he get factoryImpl created by Guice?

thanks

+6
source share
1 answer

Your existing implementation is the best you can get.

For clarity, write the general IPaymentFactory:

 public interface IPaymentFactory { IPayment create(/* ... */); } 

Thus, instances of IPaymentFactory define a single method that takes several parameters and returns an instance of IPayment. You could write the implementation yourself, and obviously you have, but Guice FactoryModuleBuilder provides interface implementations similar to this automatically. You never need to define anything else in this class: Guice will attach a constructor to you and bind it to IPaymentFactory, so you can enter instances of IPaymentFactory, call create(...) with your parameters and receive instances of IPayment.

It looks like you are going to use a factory that accepts Enum:

 public interface IPaymentFactory { IPayment create(PaymentType paymentType); } 

... but considering that CashPayment accepts one arbitrary parameter, and CardPayment accepts two arbitrary parameters, and considering that choosing between them requires matching with an arbitrary PaymentType enumeration, you did not provide Guice with almost enough information to create the right object.

Guice FactoryModuleBuilder is more suitable for combining constructor parameters with dependencies:

 // Constructor: @Inject public BitcoinPayment( @Assisted long value, // varies by instance as a constructor parameter BitcoinService bitcoinService // passed-in dependency satisfied by Guice ) { /* ... */ } // Factory interface: public IBitcoinPaymentFactory { BitcoinPayment create(long value); // users don't need to know about dependencies! } // Factory binding... install(new FactoryModuleBuilder().build(IBitcoinPaymentFactory.class)); // ...which lets Guice write the equivalent of: public GeneratedBitcoinPaymentFactory implements IBitcoinPaymentFactory { @Inject Provider<BitcoinService> bitcoinServiceProvider; @Override public BitcoinPayment create(long value) { return new BitcoinPayment(value, bitcoinServiceProvider.get()); } } 

On the one hand, a factory is dumber than you think: it just combines parameters with dependencies to get one complete list. On the other hand, this is convenient: you specify the list of dependencies once, and Guis does the rest.

In conclusion: FactoryModuleBuilder will not solve your problem, but it MAY help you create factories for CashPayment and CardPayment, which you could then introduce into your manual implementation of PaymentFactory (which must still exist in one form or another).

PS In your example, which may be a "toy problem" for demonstration, you may not need to use Guice. Guice is a great solution for service objects that require dependencies, but data objects (like payment) or other objects that don't seem to need dependencies (like GuiceService or NaiveService) can be constructed directly using constructors. Once they begin to need dependencies related to Guice injections, it should be pretty easy to make them Guice-aware.

+10
source

Source: https://habr.com/ru/post/973605/


All Articles