Java Guice-如何实现返回不同实现的工厂

Java Guice-如何实现返回不同实现的工厂,java,guice,factory,Java,Guice,Factory,假设我有一个名为Guice服务的服务,这里是它的构造函数 public GuiceService(IPayment payment) { this.payment = payment; } 我的代码使用枚举创建它 IPayment payment = new PaymentFactory.create(PaymentType.Cash); NaiveService naiveService = new NaiveService(payment); 我必须在某处进行工厂实施。像这样的

假设我有一个名为Guice服务的服务,这里是它的构造函数

public GuiceService(IPayment payment) {
    this.payment = payment;
}
我的代码使用枚举创建它

IPayment payment = new PaymentFactory.create(PaymentType.Cash);
NaiveService naiveService = new NaiveService(payment);
我必须在某处进行工厂实施。像这样的

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

  • 如果我有多个IPayment实施,该怎么办。
    (如卡付款、现金付款)
    这对一个人有效

    install(new FactoryModuleBuilder()
       .implement(IPayment.class, CashPayment.class)
       .build(IPaymentFactory.class));
    
  • 如何实现构造函数?
    它还会被支付吗?还是会得到Guice创建的factoryImpl

  • 谢谢

    您现有的实现是您所能得到的最好的

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

    public interface IPaymentFactory {
      IPayment create(/* ... */);
    }
    
    因此,IPaymentFactory的实例定义了一个方法,该方法接受一些参数并返回IPayment的实例。您可以自己编写一个实现,显然您已经编写了,但是Guice的FactoryModuleBuilder自动提供了类似这样的接口实现。您无需定义关于该类的任何其他内容:Guice将为您连接构造函数,并将其绑定到IPaymentFactory,以便您可以注入IPaymentFactory实例,使用参数调用
    create(…)
    ,并获取IPayment实例

    看起来您要的是一个接受枚举的工厂:

    public interface IPaymentFactory {
      IPayment create(PaymentType paymentType);
    }
    
    …但是,鉴于CashPayment采用一个任意参数,而CardPayment采用两个任意参数,并且考虑到它们之间的选择需要映射到任意PaymentType枚举,您没有为Guice提供足够的信息来构造正确的对象

    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());
      }
    }
    
    //构造函数:
    @注入公共比特币支付(
    @辅助长值,//作为构造函数参数随实例而变化
    BitcoinService BitcoinService//传入的依赖项由Guice满足
    ) { /* ... */ }
    //工厂界面:
    公共IBitcoinPaymentFactory{
    BitcoinPayment create(长值);//用户不需要知道依赖关系!
    }
    //工厂装订。。。
    安装(新的FactoryModuleBuilder().build(IBitcoinPaymentFactory.class));
    //…这使Guice可以编写等效的:
    公共生成的BitCoinPaymentFactory实现了IBitInputFactory{
    @注入提供者比特币服务提供者;
    @覆盖公共比特币支付创建(长值){
    返回新的BitcoinPayment(值,bitcoinServiceProvider.get());
    }
    }
    
    一方面,工厂比你想象的要简单:它只是将参数和依赖项结合起来,得到一个完整的列表。另一方面,它很方便:只需指定一次依赖项列表,Guice就可以完成其余的工作

    总而言之:FactoryModuleBuilder不会解决您的问题,但它可以帮助您创建现金支付和卡支付工厂,然后您可以将其注入手动支付工厂实现(仍需要以某种形式存在)

    另外,在您的示例中,这可能是一个用于演示的“玩具问题”,您可能不需要使用Guice。对于需要依赖关系的服务对象,Guice是一个很好的解决方案,但是数据对象(如付款)或其他似乎不需要依赖关系的对象(如GuiceService或NaiveService)可以直接使用构造函数构造。一旦他们开始需要注入Guice的依赖项,就应该很容易让他们意识到Guice