java Guice - 如何实现一个返回不同实现的工厂
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25226912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Guice - how to implement a factory that returns different implementations
提问by Bick
Lets say I have a service called Guice service and here is its constructor
假设我有一个名为 Guice 服务的服务,这是它的构造函数
public GuiceService(IPayment payment) {
this.payment = payment;
}
And my code used to create it using an Enum
我的代码曾经使用 Enum 创建它
IPayment payment = new PaymentFactory.create(PaymentType.Cash);
NaiveService naiveService = new NaiveService(payment);
And I had to have a factory implementation somewhere. Something like this
我必须在某个地方有一个工厂实现。像这样的东西
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 guess I want to use FactoryModuleBuilder.
现在我想使用 Guice,我想我想使用 FactoryModuleBuilder。
What is the way to do it if I have more that one implentation of IPayment.
(e.g. CardPayment, CashPayment)
This works for oneinstall(new FactoryModuleBuilder() .implement(IPayment.class, CashPayment.class) .build(IPaymentFactory.class));
- How do I implement the constructor ?
will it still get IPayment? or will it get the factoryImpl created by Guice?
如果我有更多的 IPayment 实现,有什么方法可以做到。
(例如 CardPayment、CashPayment)
这适用于install(new FactoryModuleBuilder() .implement(IPayment.class, CashPayment.class) .build(IPaymentFactory.class));
- 如何实现构造函数?
它还会收到 IPayment 吗?或者它会得到 Guice 创建的 factoryImpl 吗?
Thanks
谢谢
回答by Jeff Bowman
Your existing implementation is the best you can get.
您现有的实现是您能得到的最好的实现。
Let's write out a generalIPaymentFactory for clarity:
为了清楚起见,让我们写出一个通用的IPaymentFactory:
public interface IPaymentFactory {
IPayment create(/* ... */);
}
So instances of IPaymentFactory define one method, that takes in some number of parameters and returns an instance of IPayment. You could write an implementation yourself, and evidently you have, but Guice's FactoryModuleBuilder provides interface implementations like this one automatically. You never need to define anything else about that class: Guice will wire up the constructor for you, and bind it to IPaymentFactory so you can inject IPaymentFactory instances, call create(...)
with your parameters, and get IPayment instances.
所以 IPaymentFactory 的实例定义了一个方法,它接受一些参数并返回一个 IPayment 的实例。您可以自己编写一个实现,而且显然您已经这样做了,但是 Guice 的 FactoryModuleBuilder 自动提供了这样的接口实现。您永远不需要为该类定义任何其他内容:Guice 将为您连接构造函数,并将其绑定到 IPaymentFactory 以便您可以注入 IPaymentFactory 实例、create(...)
使用您的参数调用并获取 IPayment 实例。
It looks like what you're going for is a factory that takes an Enum:
看起来你想要的是一个需要枚举的工厂:
public interface IPaymentFactory {
IPayment create(PaymentType paymentType);
}
...but given that CashPayment takes one arbitrary parameter, and CardPayment takes two arbitrary parameters, and given that the selection between them requires a mapping to an arbitrary PaymentType enum, you haven't given Guice nearlyenough information to construct the right object.
......但鉴于CashPayment接受一个任意参数,并CardPayment需要两个任意参数,并给予它们之间的选择需要映射到任意PaymentType枚举,你没有给吉斯几乎足够的信息来构建合适的对象。
Guice FactoryModuleBuilder is designed more for combining constructor parameters with dependencies:
Guice FactoryModuleBuilder 的设计更多是为了将构造函数参数与依赖项相结合:
// 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 one hand, the factory is dumber than you think: It just combines parameters with dependencies to get one whole list. On the other, it's handy: you specify the dependency list once, and Guice does the rest.
一方面,工厂比你想象的要笨:它只是将参数与依赖项结合起来得到一个完整的列表。另一方面,它很方便:您指定依赖项列表一次,剩下的由 Guice 完成。
In summary:FactoryModuleBuilder won't solve your problem, but it COULD help you create factories for CashPayment and CardPayment, which you could then inject into your manual PaymentFactory implementation (which will still need to exist in some form or another).
总之:FactoryModuleBuilder 不会解决您的问题,但它可以帮助您为 CashPayment 和 CardPayment 创建工厂,然后您可以将它们注入您的手动 PaymentFactory 实现(仍然需要以某种形式存在)。
P.S. In your example, which might 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 a payment) or other objects that don't seem to need dependencies (like GuiceService or NaiveService) can be constructed directly using constructors. Once they start needing Guice-injected dependencies, it should be pretty easy to make them Guice-aware.
PS 在您的示例中,这可能是演示的“玩具问题”,您可能不需要使用 Guice。对于需要依赖的服务对象,Guice 是一个很好的解决方案,但数据对象(如支付)或其他似乎不需要依赖的对象(如 GuiceService 或 NaiveService)可以直接使用构造函数构造。一旦他们开始需要注入 Guice 的依赖项,让他们意识到 Guice 应该很容易。