uding .implement for Shipment means the implementation class // will be 'Shipment' itself, which is legal if it's not an interface. .implement(Receipt.class, RealReceipt.class) .build(OrderFactory.class));
Using the factory
Inject your factory into your application classes. When you use the factory, your arguments will be combined with values from the injector to construct an instance.
public class PaymentAction { {@literal @}Inject private PaymentFactory paymentFactory; public void doPayment(Money amount) { Payment payment = paymentFactory.create(new Date(), amount); payment.apply(); } }
Making parameter types distinct
The types of the factory method's parameters must be distinct. To use multiple parameters of the same type, use a named {@literal @}{@link Assisted} annotation to disambiguate theparameters. The names must be applied to the factory method's parameters:
public interface PaymentFactory { Payment create( {@literal @}Assisted("startDate") Date startDate, {@literal @}Assisted("dueDate") Date dueDate, Money amount); }
...and to the concrete type's constructor parameters:
public class RealPayment implements Payment { {@literal @}Inject public RealPayment( CreditService creditService, AuthService authService, {@literal @}Assisted("startDate") Date startDate, {@literal @}Assisted("dueDate") Date dueDate, {@literal @}Assisted Money amount) { ... } }
Values are created by Guice
Returned factories use child injectors to create values. The values are eligible for method interception. In addition, {@literal @}{@literal Inject} members will be injected before they arereturned.
More configuration options
In addition to simply specifying an implementation class for any returned type, factories' return values can be automatic or can be configured to use annotations:
If you just want to return the types specified in the factory, do not configure any implementations:
public interface FruitFactory { Apple getApple(Color color); } ... protected void configure() { install(new FactoryModuleBuilder().build(FruitFactory.class)); }
Note that any type returned by the factory in this manner needs to be an implementation class.
To return two different implementations for the same interface from your factory, use binding annotations on your return types:
interface CarFactory { {@literal @}Named("fast") Car getFastCar(Color color); {@literal @}Named("clean") Car getCleanCar(Color color); } ... protected void configure() { install(new FactoryModuleBuilder() .implement(Car.class, Names.named("fast"), Porsche.class) .implement(Car.class, Names.named("clean"), Prius.class) .build(CarFactory.class)); }
Implementation limitations
As a limitation of the implementation, it is prohibited to declare a factory method that accepts a {@code Provider} as one of its arguments.
@since 3.0
@author schmitt@google.com (Peter Schmitt)