Guice - 如何实现返回不同实现的工厂 [英] Guice - how to implement a factory that returns different implementations

查看:513
本文介绍了Guice - 如何实现返回不同实现的工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们说我有一个名为Guice服务的服务,这里是它的构造函数

Lets say I have a service called Guice service and here is its constructor

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

我的代码用于使用Enum创建它

And my code used to create it using an 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;

现在我想使用Guice,我想我想使用FactoryModuleBuilder。

Now I want to use Guice and I guess I want to use FactoryModuleBuilder.


  1. 如果我有更多的IP支付实施方式,该怎么做。

    (例如,CardPayment,CashPayment)

    这适用于一个

  1. What is the way to do it if I have more that one implentation of IPayment.
    (e.g. CardPayment, CashPayment)
    This works for one

install(new FactoryModuleBuilder()
   .implement(IPayment.class, CashPayment.class)
   .build(IPaymentFactory.class));


  • 如何实施构造函数?

    它还能获得IPayment吗?或者它会得到Guice创建的factoryImpl吗?

  • 谢谢

    推荐答案

    您现有的实施是最好的。

    Your existing implementation is the best you can get.

    为了清楚起见,让我们写出一个通用 IPaymentFactory:

    Let's write out a general IPaymentFactory for clarity:

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

    所以IPaymentFactory的实例定义了一个方法,它接受了一些参数和返回IPayment的实例。你可以自己编写一个实现,显然你有,但Guice的FactoryModuleBuilder自动提供这样的接口实现。你永远不需要定义关于该类的任何其他内容:Guice会为你构建一个构造函数,并将它绑定到IPaymentFactory,这样你就可以注入IPaymentFactory实例,调用 create(...)使用你的参数,并获得IPayment实例。

    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.

    看起来你想要的是一个带Enum的工厂:

    It looks like what you're going for is a factory that takes an Enum:

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

    ...但鉴于CashPayment需要一个任意参数,而CardPayment需要两个任意参数,并且鉴于它们之间的选择需要映射到任意PaymentType枚举,您没有给Guice 几乎足够的信息来构造正确的对象。

    ...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 nearly enough information to construct the right object.

    Guice FactoryModuleBuilder设计用于将构造函数参数与依赖项组合:

    Guice FactoryModuleBuilder is designed more 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());
      }
    }
    

    一方面,工厂比你想象的更笨:它只是将参数与依赖关系结合起来得到一个完整的列表。另一方面,它很方便:你指定依赖列表一次,Guice完成其余的工作。

    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.

    总结: FactoryModuleBuilder无法解决你的问题,但它可以帮助你为CashPayment和CardPayment创建工厂,然后你可以注入你的手动PaymentFactory实现(它仍然需要以某种形式存在)。

    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).

    PS在您的示例中,可能是演示的玩具问题,您可能不需要使用Guice。 Guice对于需要依赖的服务对象是一个很好的解决方案,但是可以使用构造函数直接构造数据对象(如支付)或其他似乎不需要依赖的对象(如GuiceService或NaiveService)。一旦他们开始需要注入Guice的依赖项,就可以很容易地使它们具有Guice感知能力。

    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.

    这篇关于Guice - 如何实现返回不同实现的工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆